背景介绍:学习就是一个在原有基础上不断提高的过程,在耿建玲老师视频的学习之后,我们缺少了最重要的一步就是实际操作,有些东西看似很简单,但是真正做的时候,就会遇到了困难。写这篇博客的目的就是在原来的基础上,提高一下自己,虽然现在死锁还没有实际用到,但是还是想接触并通过实践来提高一下自己的学习。
知识理解:
事务回滚:在银行给别人转账,但可能钱已经扣了,对方也没有得到钱,自己肯定不乐意了,然后银行就进行事务回滚,不保存你刚才转账的操作,恢复到原来未转账的状态。
步入正题:
我们的数据库中是不允许死锁发生的,死锁会导致其中一个事务的回滚,整个事务的提交失败,而且死锁还会占用大量的资源,使我们的系统运行起来会缓慢,所以要避免死锁的发生。
一、死锁的创建:
新建查询sa(53):
创建一个事务t1,但是不提交。然后执行。
BEGINTRAN t1 --创建一个事务更新表
UPDATEOnLine_Info
SETontime =GETDATE()
系统会默认的在这个表中上一个锁,表示这个事务是未提交状态。
新建查询sa(54):
然后再创建另一个事务t2,也不进行提交。
BEGINTRAN t2 --创建另一个事务更新表
updateLine_Info
SETontime =GETDATE()
这个也是,Line_Info 也被上了一个锁。
然后在sa(53)中:
更新Line_Info表然后执行。
updateLine_Info
SETontime =GETDATE()
此时会发现,系统会一直处于等待状态,因为此时事务t2中的Line_Info表是锁定的。所以,只有当t2事务提交或着回滚之后,资源被释放出来,等待状态才会结束。
现在让t2事务中执行。让t2事务争夺Online_Info表中的资源。
updateOnLine_Info
SETontime =GETDATE()
执行成功后,我们在t1事务中,就可以看到。事务t1被作为死锁的一个牺牲品。所以t1整个事务就已经回滚了。
整体的效果:
事务t1是先访问Online_Info表,然后再访问Line_Info表。
事务t2是先访问Line_Info表,然后在访问Online_Info表。
由于这两个事务访问的顺序不一致,导致出现了死锁。
二、死锁的监测
有两种办法。
方法一:
通过dbcc命令,将死锁信息记录到我们的日志中去。
执行命令后,在重复执行刚刚创建死锁的步骤。就是先让事务t2回滚(rollback)。也可以用COMMIT(事务提交语句)提交事务(对应的语句看数据库自考书)
dbcc traceon(1222,1204,3605,-1)
知识点积累:
3605-将DBCC的结果输出到错误日志
1222 -返回参与死锁的锁的资源和类型,以及使用了不符合任何XSD 架构的 XML 格式的受影响的当前命令
-1 以全局方式打开指定的跟踪标记。
1204 返回参与死锁的锁的资源和类型,以及受影响的当前命令
/* 对于这个命令的理解,还有欠缺,等以后在解决,暂时储备的知识还有限。*/我们可以同过日志文件查看器,来判断在哪里个语句出现了错误。这里面虽然有了一个死锁的日志,但是这种方法不能很好的直接查看死锁产生的原因。
不如方法二好:
方法二:(设置死锁的追踪)
工具----SQL Sever Profiler---事件选择---显示所有事件
Deadlock graph这个是图形化显示死锁。
再执行创建死锁的操作,这样就可以对发现死锁的语句进行追踪了。
同时这样就可以看到到底是哪条语句出现了死锁,然后就可以对这个语句进行修改了。 (错误的语句会显示出来)
总结:
这个死锁的学习,在学习耿建玲视频的时候,就只是概念上理解了,但是实践的时候,事物相互之间的关系还是有点混乱,大概用了四个番茄的时间完成了对死锁的创建和监测。总之,有收获、有努力、有动力!