两个用户同时更新一张表里的两条记录但顺序不同会不会死锁?
A用户
update 表 set je=je+1 where id=1
update 表 set je=je+1 where id=2
B用户
update 表 set je=je+1 where id=2
update 表 set je=je+1 where id=1
当两个用户同时操作时会不会互相锁定,造成死锁?
------解决方案-------------------- 这个是用来教学死锁的典型案例之一....基本上就逃不掉死锁的可能了
------解决方案-------------------- 除非你切换了其他隔离级别
------解决方案-------------------- 1、按顺序更新,比如你那两个,同时都更新id相同的,这样一般只是阻塞而已,不至于死锁。
2、使用乐观并发,比如行版本存储技术来避免。
3、改设计,这个太痛苦了。
4、合理的查询和索引,加快速度。
5、保证事务尽可能短,比如你上面,如果不是非要两个id的update都放在一起,那最好分开两个事务
------解决方案-------------------- 按相同的順序更新即可.
------解决方案-------------------- 我做的一个实验,就是这种情况,两个事务,都访问同一个表的,2条数据,由于这是访问的顺序不同,导致了死锁
通过DBCC Page查看在SQL Server中哪行数据被锁住了?
http://blog.csdn.net/sqlserverdiscovery/article/details/13291629
------解决方案--------------------
解决和预防死锁的方法
下面的方法有助于将死锁减至最少:
1.按同一顺序访问对象。
2.避免失误中的用户交互。
3.保持事务简短并处于一个批处理中。
4.使用较低的隔离级别,如:使用nolock参数,让SELECT语句不要申请S锁。
5.调整索引,以调整执行计划,减少锁的申请数目,从而消除死锁。
6. 升级锁的粒度,将死锁转化成一个阻塞问题。
死锁问题的定位
死锁检测是由锁监视器这个系统线程执行的,会定期搜索SQL Server里的所有任务,默认时间间隔为5秒.
检测到死锁后,数据库引擎通过选择其中一个线程作为死锁牺牲品来结束死锁,并回滚死锁牺牲品的事务,会释放事务持有的所有锁,
将1205错误返回到应用程序,这将使其他线程的事务解锁,并继续运行.
默认情况下,数据库引擎选择运行回滚开销最小的事务的会话作为死锁牺牲品.
为了查看死锁信息,数据库引擎提供了监视工具:
1.两个跟踪标志1204和1222。
跟踪标志1204和1222会向SQL Server错误日志返回捕获的信息。
跟踪标志1204会报告由死锁所涉及的每个节点设置格式的死锁信息,它是SQL Server 2005之前版本就有的功能。
跟踪标志1222是SQL Server 2005才开始有的新功能,会设置死锁的信息格式,顺序为先按进程,然后按资源,
1222的结果不但基本包含了1204的所有信息,还包含了许多1204没有的信息,
所以在SQL Server 2005以后,可以直接使用1222来跟踪死锁: DBCC TRACEON(1222,-1).
2.SQL ServerProfiler中的死锁图形事件.
------解决方案-------------------- 如果不放在同一个事务里面是根本不会死锁的
开两个窗口测试
--BEGIN TRAN
WAITFOR TIME '09:59:54';
update [ta] set id=id+1 where id=2
update [ta] set id=id+1 where id=1
--COMMIT TRAN
------解决方案-------------------- 引用: A用户
update 表 set je=je+1 where id=1
update 表 set je=je+1 where id=2
B用户
update 表 set je=je+1 where id=2
update 表 set je=je+1 where id=1
当两个用户同时操作时会不会互相锁定,造成死锁?
需看具体情况,简单讲:
当id=1,id=2的记录在同一个数据页时,可能产生阻塞.
当id=1,id=2的记录在不同的数据页时,可能产生死锁.
不明白可以私信找我,给你2个测试案例.
------解决方案-------------------- 引用: 那么多用户同时更新一张表的多条记录,怎样才能避免死锁呢?
同个用户的多个更新,不加事务(transaction).