我正在阅读有关InnoDB's 隔离级别的内容,这在很大程度上是有道理的,但我不明白为什么是unrepeatable reads一件坏事?不应该反过来吗?
举些例子:
因此,假设我们有一个用于销售产品的库存列,每次有人购买一件商品时,我们都会从该列中取出 1 件商品,使用Repeatable read或serializable隔离级别会不会破坏数据完整性?
例如:
TX A: start transaction;
TX B: set session transaction isolation level repeatable read;
TX B: start transaction;
TX A: select stock from products; -- val = 8
TX B: select stock from products; -- val = 8
TX A: update products set stock = stock - 1; -- val = 7
TX B: select stock from products; -- val = 8
TX A: …Run Code Online (Sandbox Code Playgroud) 如果我创建一个表。
CREATE TABLE foo AS
SELECT CASE WHEN random() > 0.5 THEN x END AS x
FROM generate_series(1,10) AS x;
Run Code Online (Sandbox Code Playgroud)
然后我在事务中运行以下命令
BEGIN;
SELECT count(*)
FROM foo
WHERE x IS NOT NULL;
--time
SELECT count(*)
FROM foo
WHERE x IS NOT NULL;
END;
Run Code Online (Sandbox Code Playgroud)
在什么交易级别下我的结果保证在交易中保持不变?
我们目前有一些ALLOW_PAGELOCKS设置为关闭的索引。这样做大概是为了减少死锁。但是,我怀疑当时它真的会产生影响。
现在我试图了解 SQL Server 何时实际选择开始锁定页面而不是聚集索引中的键。我最近问过 Jonathan Keyhaisas,他告诉我如果我在多个后续页面上触摸行,就会发生这种情况。但是,我没有通过使用示例查询更新聚集索引中的行来获得任何独占页面锁。
你能通过示例查询和表帮助我更好地理解页锁吗?我正在运行 SQL Server 2008 SP4。
提前致谢
马丁
设置脚本
CREATE TABLE t2 ( [col1] INT, [col2] INT );
DECLARE @int INT;
SET @int = 1;
WHILE (@int <= 1000)
BEGIN
INSERT INTO t2
([col1], [col2])
VALUES (@int*2, @int*2);
SET @int = @int + 1;
END
GO
create clustered index cl on t2(col1)
create index ncl on t2(col2)
Run Code Online (Sandbox Code Playgroud)
我运行一个简单的更新并在读提交隔离级别保持事务打开。
begin tran
update t2 set [col2]=[col2]+1 where col1=6
Run Code Online (Sandbox Code Playgroud)
如果我在另一个会话中检查 sp_lock,我会得到以下结果
我想了解的是非聚集索引(indid 2)上的键锁。为什么非聚集索引上有两个键锁?
如果我检查第 248 页上的 dbcc 页面,我可以找到明显的一个 ((1bfceb831cd9)),它是记录 6 的条目的锁,该条目已更改为 7。下面 DBCC PAGE 的输出
我想了解的是另一个键锁(5ebca7ef4e2c)的目的是什么以及它的锁定是什么。
在此问题之后,是否更改varchar()表重写或锁定比更改CHECK约束花费更多时间的结果的长度限制(类型修饰符)?从那个问题你可以看到Brandur 的说法,
如果您想更改长度,则
ALTER TABLE需要排他锁(请参阅https://www.postgresql.org/docs/current/static/sql-altertable.html ...)。改变CHECK是即时的。在回答一个问题,质疑文CHECK (char_length(email) <= 255)VSvarchar(255)
似乎这可能起源于 Depesz 在 2010 年发表的帖子“CHAR(X) VS. VARCHAR(X) VS. VARCHAR VS. TEXT – 2010-03-03 更新”
那么,当你[使用 varchar] 使限制更大时会发生什么?
PostgreSQL 必须重写该表。这有两个非常重要的缺点: 1. 操作时需要对表进行排他锁 2. 在非平凡表的情况下,将花费相当多的时间
您可以在此处 (2017)的评论中再次看到这一点,
尽管如此,当我想将我
VARCHAR(50)的VARCHAR(250).
再次在这里(2012),
顺便说一句:如果可以避免的话,我从不使用 varchar - 特别是不使用长度修饰符。它几乎提供了类型文本无法提供的任何内容。如果我需要长度限制,我会使用一个列约束,它可以在不重写整个表的情况下进行更改。
显然还有其他人怀疑这一说法。
仅仅解决这个单一的要求可能是值得的。
我需要一个例程来有效识别哪些查询导致阻塞。这与我之前的问题如何找到仍然持有锁的查询有关?.
我知道网上有很多关于这方面的资料,但所有这些资料都是基于活动会话上的最后一条 SQL 语句很可能是获取锁的那个(因此产生了阻塞),这并不总是真的(在我的情况下,从来没有)。
我已将 设置blocking-process-threshold为 30 秒并开始分析阻塞进程报告 (BPR)。
当达到阈值时,每次发生阻塞时都会触发这些报告。
它包含有关阻塞 spid 和阻塞 spid 的信息。
通常,阻塞 spid 会在获取并持有资源(表、页或行)锁的语句之后运行几个语句:因此,不管报告内容如何,我仍然不知道究竟是哪个查询导致了该阻塞。
通常 SQL Server DMV 只显示每个 的最后一个 SQL 文本session_id,与活动锁(例如sys.dm_tran_locks)相关的 DMV也没有解决这个问题。
调整阻塞的查询在这里不是最好的方法:我们的应用程序全部基于嵌入在客户端代码中的动态 SQL,我们不使用存储过程,并且基于我目前看到的阻塞,所有阻塞的查询都被正确索引并写成。
我认为解决这个问题的一个选项是收集候选查询,这可能会产生阻塞,然后使用在 BPR 上收集的时间戳和 spid 查找此信息。你同意?如果是这样,您能否指出一种使用 xEvents 以尽可能少的开销来做到这一点的方法?
performance sql-server transaction locking blocking performance-tuning
有没有人有一个很好的 Sql Alert 来发送电子邮件通知,当查询阻塞发生超过几分钟时?我知道如何编写自己的代码,但是在 Internet 上似乎是一个很好的代码库。如果可能,请在没有事件通知的情况下给出答案。
我喜欢下面这个: 阻止发生时的电子邮件通知
我避免使用这些,因为它们使用我听说已被弃用的 sys.processes: 自动检测阻塞
这与第一个类似,但没有那么多细节: 查找长时间运行的查询
在实施之前尝试找到好的解决方案或共识。随意发送解决方案或在下面编辑一个。
谢谢,
注意:下面的一个似乎有一个不必要的临时表步骤,可能可以消除,只需一封 sql 电子邮件。
*/
SET NOCOUNT ON
-- Checked for currently running queries by putting data in temp table
SELECT s.session_id
,r.STATUS
,r.blocking_session_id
,r.wait_type
,wait_resource
,r.wait_time / (1000.0) 'WaitSec'
,r.cpu_time
,r.logical_reads
,r.reads
,r.writes
,r.total_elapsed_time / (1000.0) 'ElapsSec'
,Substring(st.TEXT, (r.statement_start_offset / 2) + 1, (
(
CASE r.statement_end_offset
WHEN - 1
THEN Datalength(st.TEXT)
ELSE r.statement_end_offset
END - r.statement_start_offset
) / 2
) + 1) AS …Run Code Online (Sandbox Code Playgroud) 我的研究表明,我可以在短时间内删除表中的一列(前提是我获得了排他锁),因为这只是元数据更改。
该表有两个不同的服务,不断插入和更新记录。太热了。如果不开发这种活动级别的完整复制环境,我怎么能确保像这样的陈述
ALTER TABLE x DROP COLUMN y
Run Code Online (Sandbox Code Playgroud)
会成功获得排他锁,快速做drop,然后解锁表吗?
SQL Server 将如何将此请求排队(例如,先进先出)?我能确定 DROP COLUMN 真的只需要几分钟吗?
在 PROD 中长时间锁定此表是不可接受的,因此我试图避免出现意外。
其他注意事项:稍后我将在线重新索引以对索引进行碎片整理并回收空间。
我在我的 SQL 程序之一中有一个类似于下面的代码,
declare @rowcount int
update table1
set value = @value
where id = @id
select @rowcount = @@ROWCOUNT
if ( @rowcount = 0 )
begin
insert into table1(id, value1,value2...)
select (@id, @value1, @value2...)
end
Run Code Online (Sandbox Code Playgroud)
但它很少失败,比如一天一次等。这意味着数据存在于表中,@@rowcount 为 0,它试图插入数据和主键冲突发生。这里插入的所有值,即。id、value1、value2 等是整数。有什么想法吗?
我有这个查询
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
UPDATE c
SET c.Score = 2147483647
FROM dbo.Comments AS c
WHERE c.Id BETWEEN 1 AND 5000;
Run Code Online (Sandbox Code Playgroud)
哪个有这些统计数据
+--------------+---------------+---------------+-------------+
| request_mode | locked_object | resource_type | total_locks |
+--------------+---------------+---------------+-------------+
| RangeX-X | Comments | KEY | 2429 |
| IX | Comments | OBJECT | 1 |
| IX | Comments | PAGE | 97 |
+--------------+---------------+---------------+-------------+
Run Code Online (Sandbox Code Playgroud)
我想知道 IX,它是一个意图锁。这是什么意思,为什么桌子上有一个它自己?据我了解,它不是真正的锁,而是 SQL Server 使用(或由事务设置?)来指示可能发生锁的更多东西。
以上是对的吗?
locking ×10
sql-server ×7
blocking ×2
postgresql ×2
transaction ×2
alerts ×1
concurrency ×1
index ×1
innodb ×1
mvcc ×1
mysql ×1
performance ×1
primary-key ×1