我需要在sql server表上执行un update语句,此表由另一个进程同时使用.因为有时会发生僵局.您是否建议隔离级别以避免或最小化此死锁?
我正在调查一个死锁,并且在探查器的死锁xml文件中看到进程process5332cf8在快照隔离级别(isolationlevel="snapshot (5)")下运行事务。
但是不知何故,它在页面上保持了IX锁,并希望再获取一个。
这可能是什么原因(除了在发生冲突的中间阶段将隔离级别更改为非快照之外)?
我是否缺少有关Snapshot IL的信息?
PS:完整的xml:http : //ideone.com/yuU9td
假设您有一个具有以下定义的表:
CREATE TABLE public.positions
(
id serial,
latitude numeric(18,12),
longitude numeric(18,12),
updated_at timestamp without time zone
)
Run Code Online (Sandbox Code Playgroud)
你在这样的表中有 50,000 行。现在出于测试目的,您将运行如下更新:
update positions
set updated_at = now()
where latitude between 234.12 and 235.00;
Run Code Online (Sandbox Code Playgroud)
该语句将更新 50,000 行中的 1,000 行(在此特定数据集中)
如果您在 30 个不同的线程中运行这样的查询,MySQL innodb 将成功,而 postgres 将因大量死锁而失败。
为什么?
假设我们使用create new table并为我们的数据库启用快照隔离:
alter database database_name set allow_snapshot_isolation on
create table marbles (id int primary key, color char(5))
insert marbles values(1, 'Black') insert marbles values(2, 'White')
Run Code Online (Sandbox Code Playgroud)
接下来,在会话1中开始一个快照事务:
set transaction isolation level snapshot
begin tran
update marbles set color = 'Blue' where id = 2
Run Code Online (Sandbox Code Playgroud)
现在,在提交更改之前,在会话2中运行以下命令:
set transaction isolation level snapshot
begin tran
update marbles set color = 'Yellow' where id = 2
Run Code Online (Sandbox Code Playgroud)
然后,当我们提交会话1时,会话2将失败,并显示有关事务中止的错误 - 我知道这可以防止更新丢失.
如果我们逐个执行此步骤但具有任何其他隔离级别,例如:可序列化,可重复读取,读取提交或未提交读取,则会执行此会话2,从而对表进行新的更新.有人可以解释一下我为什么会这样吗?对我来说,这是一种丢失的更新,但似乎只有快照隔离才能阻止它.
t-sql sql-server transactions transaction-isolation isolation-level
deadlock ×2
sql-server ×2
transactions ×2
database ×1
mysql ×1
postgresql ×1
snapshot ×1
sql ×1
t-sql ×1