Teradata:你如何调试“由于死锁导致的事务中止”错误?

时间:2012-08-07 23:38:43

标签: deadlock teradata

最近,当我们更新其中一个表中的记录时,我们遇到了错误Transaction ABORTed due to Deadlock。有什么东西锁定在这张桌子上并且它没有被释放,但我花了很多工作时间试图追踪它并且它仍然没有我。

虽然错误是随机的,但我确实知道我需要重复的步骤的重复周期才能最终触发它。但是,我查询了dbc.DBQLogTbl并查看了错误发生前后2分钟执行的所有SQL,没有任何表似乎没有访问锁定的任何表中选择。此外,在错误发生后,我将按F5将Web表单重新发送回服务器以重复完全相同的更新集,它将起作用。

我的预感是我们的ASP.NET应用程序之外的某些进程正在锁定表,因为我已经检查了我们的应用程序正在执行的所有SQL。我认为必须找到一种方法来找出已经在表上放置锁的特定SQL。

2012年8月9日其他信息:基于我在查询dbc.DBQLogTbl并按{{1}排序时所看到的内容,在同一事务中按此顺序发生以下所有操作}}:

  • 更新员工表
  • 锁定行以进行访问select * from employeesecurity,其中empid = X(执行此操作以获取当前员工记录以查看是否有任何更改)
  • 如果有变更,请更新上述的职业安全记录
  • 更新employeeconfig表(此处始终发生死锁错误)

之前我没有提到过这个问题,但死锁错误发生在我根本没有选择的表上。加载页面时,我会从employeeconfig视图中读取,但在视图中指定了firststeptime

回答Rob的4个问题:

  • 这只是一次交易。
  • 正如我在最新的更新中所述,锁定的表格甚至不是从中选择的表格。
  • 所有查询都使用locking row for access
  • 我们从视图locking row for access中进行选择。此视图使用employeeconfigemployeeconfig表中进行选择。查询视图本身时,我们不使用locking row for access

至于处理死锁,我宁愿没有代码只是尝试重新提交它,因为这似乎是一个需要修复的问题。正如你所说,Rob,我对locking row for access的访问可能是有限的,所以也许我看不到正在发生的一切。我一直与DBA保持联系,今天会再次跟进。

2 个答案:

答案 0 :(得分:3)

识别中止的交易

死锁条件应该导致导致死锁的两个事务都被中止。我通常会看到Informatica推送优化的死锁,试图并行创建临时视图并在创建视图所需的DBC表上进行死锁。与您的情况一样,我们的Informatica情况完全是随机的。由于死锁,我们可以在没有中止的情况下持续数周或数月。

您可以通过查询DBQL日志表以查找包含ErrorCode = 2631编辑:已修复错误代码)和ORDER BY StartTime DESC的交易的可疑交易。这将为您提供由于死锁而中止的每个事务。导致死锁的事务对如果不按排序配对,则应该相当接近。

如果你的DBA已经限制了对历史DBQL数据的看法,那么它可能会妨碍你找到根本原因的能力。如果是这种情况,您需要与DBA团队合作以确定问题所在。由于给定查询的SQLText中包含的信息,查询信息仅限于开发人员并不罕见。这只是要考虑询问您的查询是否不会产生任何结果。

识别可能发生中止交易的原因

注意:这不是一个详尽的清单。

关于这些死锁条件的更糟糕的事情是它们通常是随机发生的。墨菲定律规定,这些随机事件将在您睡觉,度假或其他您不希望被打扰的事件中发生。根据您的具体情况,您可以简单地重新提交已死锁的事务。

这将要求您首先了解如何抵达死锁状态。

  • 如果两个交易试图操纵相同的记录,您的数据模型是否支持缓慢变化的维度,以便您记录每次发生的变化?
  • 如果是读取事务并且访问同一记录的更新事务可以调整锁定粒度和持续时间以最小化机会吗?
  • 您使用的是ACCESS还是READ
  • 您的SELECT语句是否通过1:1视图访问该表,该视图使用ROWHASH ACCESS锁定,从而允许优化程序将锁定从最精细级别升级到所需级别交易有问题? (例如LOCKING ROW FOR ACCESS SELECT * FROM DBC.DBCInfo;
  • 删除了有关更新声明的行锁定的建议。

处理已中止的交易

根据您遇到的死锁情况,您可以选择让您的进程尝试重新提交失败的事务预定次数。您可能遇到这样的情况:一个进程可能会重新提交,另一个进程可能必须保持其状态,以便其他人在继续之前进行验证。前者可能是您的Web应用程序,后者可能是一个无法盲目重启的复杂ETL流。

您应该记录发生这种情况或有其他报告机制来跟踪这些事件。

答案 1 :(得分:0)

在关系数据库中,中止事务本身不是错误,而只是客户端从一开始就重试事务的请求,因为另一个并发事务可能已经改变了现在发出的客户端已经观察到的条件 - 交易。通过偶尔允许事务中止(并由客户端重试),底层关系数据库可以进行重要的性能优化,例如允许许多事务同时运行,即使这会导致很小的死锁机会。

为什么数据库服务器在这些情况下不会重试事务本身?因为客户端可能正在使用从事务中的一个查询返回的数据来影响在同一事务中的后续更新中要执行的更新类型。因此,重新进行交易的责任在于客户处于交易中止的罕见(但完全正常和预期)的情况。

所以答案是:中止的事务是完全正常的,你只需要从客户端重试它们。但正如Rob指出的那样,根据您正在进行的事务类型,这可能很容易或很难(例如,如果您正在进行2小时的ETL过程,您可能想要弄清楚如何减少死锁的可能性)