微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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,请推出自己的互斥锁.

原文地址:https://www.jb51.cc/mssql/76957.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐