sql-server – 使用SQL Server的SELECT JOIN语句导致的死锁

当执行带有sql Server似乎的两个表的JOIN的SELECT语句时
单独锁定语句的两个表.例如通过类似的查询
这个:
SELECT ...
FROM
    table1
    LEFT JOIN table2
        ON table1.id = table2.id
    WHERE ...

我发现锁的顺序取决于WHERE条件.该
查询优化器尝试生成只读取尽可能多的执行计划
必要的行.因此,如果WHERE条件包含table1列
它将首先从table1获取结果行,然后获取相应的行
table2中的行.如果列来自table2,它将以另一种方式执行
回合.更复杂的条件或索引的使用可能会产生影响
查询优化器的决定也是如此.

当语句读取的数据应在事务中稍后更新时
使用UPDATE语句,不保证UPDATE的顺序
语句匹配用于从2个表中读取数据的顺序.
如果另一个事务在事务更新时尝试读取数据
这些表在执行SELECT语句时可能导致死锁
在UPDATE语句之间,因为SELECT都无法获得锁定
一个表也不能UPDATE获取第二个表上的锁.对于
例:

T1: SELECT ... FROM ... JOIN ...
T1: UPDATE table1 SET ... WHERE id = ?
T2: SELECT ... FROM ... JOIN ... (locks table2,then blocked by lock on table1)
T1: UPDATE table2 SET ... WHERE id = ?

两个表都表示类型层次结构,并始终一起加载.所以
使用带有JOIN的SELECT加载对象是有意义的.加载两个表
单独不会给查询优化器找到最好的机会
执行计划.但是因为UPDATE语句只能更新一个
在对象加载对象时,这会导致死锁
由另一个事务更新.对象的更新通常会导致UPDATE
两个表属于属于不同类型的对象的属性
类型层次结构已更新.

我试图向SELECT语句添加锁定提示,但事实并非如此
改变问题.它只会导致SELECT语句中的死锁
两个语句都试图锁定表,一个SELECT语句获取
与另一个陈述相反的顺序.也许有可能
加载更新数据始终使用相同的语句强制锁定
以相同的顺序.这样可以防止两个事务之间出现死锁
想要更新数据,但不会阻止只读取的事务
数据到死锁,需要有不同的WHERE条件.

迄今为止唯一的工作方式似乎是读取可能无法锁定
一点都不使用sql Server 2005,可以使用SNAPSHOT ISOLATION完成此操作.该
sql Server 2000的唯一方法是使用READ UNCOMMITED隔离
水平.

我想知道是否还有其他可能阻止sql Server
从导致这些僵局?

解决方法

当读者不阻止编写者时,在快照隔离下永远不会发生这种情况.除此之外,没有办法阻止这样的事情.我在这里写了很多repro脚本: Reproducing deadlocks involving only one table

编辑:

我无法访问sql 2000,但我会尝试使用sp_getapplock序列化对象的访问,以便读取和修改永远不会同时运行.如果您不能使用sp_getapplock,请推出自己的互斥锁.

相关文章

SELECT a.*,b.dp_name,c.pa_name,fm_name=(CASE WHEN a.fm_n...
if not exists(select name from syscolumns where name=&am...
select a.*,pano=a.pa_no,b.pa_name,f.dp_name,e.fw_state_n...
要在 SQL Server 2019 中设置定时自动重启,可以使用 Window...
您收到的错误消息表明数据库 'EastRiver' 的...
首先我需要查询出需要使用SQL Server Profiler跟踪的数据库标...