【问题标题】:Teradata: How do you debug "Transaction ABORTed due to Deadlock" errors?Teradata:您如何调试“由于死锁而导致事务中止”错误?
【发布时间】:2013-10-07 02:22:27
【问题描述】:

最近,当我们去更新我们的一个表中的记录时,我们遇到了错误Transaction ABORTed due to Deadlock。有东西在这张桌子上加了一把锁,它没有被释放,但我花了几天的时间试图追踪它,但它仍然让我难以捉摸。

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

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

2012 年 8 月 9 日附加信息:根据我在查询dbc.DBQLogTbl 和通过firststeptime 订购时看到的情况,在同一事务中按此顺序发生以下所有情况:

  • 更新员工表
  • locking row for access select * from employeesecurity where empid = X(执行此操作以获取当前员工记录以查看是否有任何更改)
  • 如果有变化,更新上述员工安全记录
  • 更新employeeconfig表(这里总是出现死锁错误)

我之前没有提到这一点,但是死锁错误发生在我根本没有从中选择的表上。当页面加载时,我确实从一个employeeconfig 视图中读取,但在视图中指定了locking row for access

回答 Rob 的 4 个问题:

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

就处理死锁而言,我不希望代码只是尝试重新提交它,因为这似乎是一个需要修复的问题。正如你所说,Rob,我对dbc.DBQLogTbl 的访问可能受到限制,所以我可能无法看到正在发生的一切。我一直在联系 DBA,今天会再次跟进。

【问题讨论】:

  • 我认为如果您遇到死锁错误,您的应用程序至少会尝试一次重试已中止的事务。您的环境是否使用 Viewpoint?如果是这样,您是否可以将其与 Rewind 功能和 Query Monitor portlet 一起使用?
  • 是的,我们使用视点,但我没能弄清楚。我尝试使用从查询 dbc.DBQLogTbl 中获得的会话 ID,但 ViewPoint 似乎从未找到它。此外,查询监视器中的 SQL 选项卡始终显示为灰色。有没有其他方法可以找出哪些 SQL 锁定了表,或者 ViewPoint 几乎是唯一的选择?
  • Viewpoint 只会帮助识别在您的事务中止时处于活动状态的其他会话。根据在 Viewpoint 上为您的角色设置的 portlet 权限,SQL 可能不可见。 (参见 DBA 团队。)
  • 更新语句的“EmployeeConfig”表的锁定级别是多少?我假设您正在执行单行更新并在主索引上进行限定。
  • 是的,主索引上的单行更新。我没有为更新指定任何锁定。基本上,我只是使用update employeeconfig set field = x where id = y

标签: deadlock teradata


【解决方案1】:

识别中止的事务

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

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

如果您的 DBA 以任何方式限制了针对历史 DBQL 数据的视图,则可能会妨碍您找到根本原因的能力。如果是这种情况,您将需要与您的 DBA 团队一起找出问题所在。由于 SQLText 中包含给定查询的信息,因此查询信息仅限于开发人员的情况并不少见。这只是要考虑询问您的查询是否没有产生任何结果。

确定可能发生中止交易的原因

注意:这不是一个详尽的列表。

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

这将要求您首先了解您是如何达到死锁条件的。

  • 如果是两个事务试图操作相同的记录,您的数据模型是否支持缓慢变化的维度,以便您记录每次发生的变化?
  • 如果是读取事务和更新事务访问同一条记录,您是否可以调整锁定粒度和持续时间以最大限度地减少机会?
  • 您使用的是ACCESS 还是READ 锁定?
  • 您的SELECT 语句是否通过使用ROWHASH ACCESS 锁定的1:1 视图访问表,从而允许优化器将锁定从最细粒度级别升级到相关事务所需的级别? (例如LOCKING ROW FOR ACCESS SELECT * FROM DBC.DBCInfo;
  • 删除了对 UPDATE STATEMENT 进行 ROW LOCKING 的建议。

处理中止的交易

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

您应该在某处记录发生这种情况,或者使用其他一些报告机制来跟踪这些事件。

【讨论】:

  • 所以我尝试查询该错误代码(实际上是2631),唯一出现的 SQL 出现在我打开的事务中。但是,我想我知道如何触发错误,只是不知道为什么会发生。请参阅我的答案的更新。
  • 我更新了我的问题。我很感激你到目前为止所付出的时间,但如果你无能为力,我会理解的。我需要在本周末之前解决这个问题,因为我们正在部署这个版本,所以我一定会用我发现的内容更新这个问题。
  • DBC.DBQLogTbl 实际表名
【解决方案2】:

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

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

所以答案是:中止的事务是完全正常的,您只需从客户端重试它们。但正如 Rob 所指出的,这可能是容易的还是困难的,具体取决于您正在执行的事务类型(例如,如果您正在执行 2 小时的 ETL 过程,您可能想弄清楚如何减少死锁的可能性) .

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-02
    • 2014-06-15
    • 2013-02-14
    • 1970-01-01
    • 1970-01-01
    • 2023-03-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多