据我了解,涉及行锁定的死锁的典型情况需要四个SQL语句。二合一事务更新行A和行B,然后另外两个在单独的事务中更新相同的行,并且需要相同的锁,但顺序相反。
事务1在事务2可以请求它之前获取行A上的锁定,事务2在事务1获得它之前获得行B上的锁定,并且两者都不能获得剩余的所需锁定。必须回滚一个或任一事务,因此另一个事务可以完成。
当我在死锁后查看Oracle跟踪文件时,它似乎只突出显示两个查询。这些似乎是每笔交易中的最后一笔。
如何识别每个事务中涉及的其他语句,或者Oracle跟踪文件中是否缺少这些语句?
如果需要,我可以包含特定跟踪文件的相关位。
答案 0 :(得分:5)
你正确的是,在一个典型的行级死锁中,你将会话1执行将锁定第1行的sql_a。然后会话2将执行将锁定第2行的sql_b。然后会话1将执行sql_c尝试锁定第2行,但会话2尚未提交,因此会话1开始等待。最后,会话2出现,它发出sql_d,试图锁定第1行,但是,由于会话1持有该锁,它开始等待。三秒钟后,检测到死锁,其中一个会话将捕获ORA-00060并写入跟踪文件。
在这种情况下,跟踪文件将包含sql_c和sql_d,但不包含sql_a或sql_b。
问题是信息真的无法在任何地方使用。考虑您执行DML,如果不存在则启动事务,生成一堆撤消和重做,并进行更改。但是,一旦发生这种情况,会话就不再与该SQL语句相关联。真的没有什么干净的方法可以回去查找这些信息。
另一方面,sql_c和sql_d是发生死锁时与这些会话关联的语句,因此,Oracle显然可以识别它们,并将其包含在跟踪文件中。
所以,你说得对,关于sql_a和sql_b的信息不在追踪中,而且它真的不容易获得。
希望有所帮助。