首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >避免死锁MySQL/UniDAC/Delphi

避免死锁MySQL/UniDAC/Delphi
EN

Stack Overflow用户
提问于 2013-07-25 04:14:00
回答 1查看 1.4K关注 0票数 1

我在访问MySQL数据库的两个应用程序中使用了UniDAC (Devart)。在一个应用程序执行一些繁重的更新更新操作期间,我偶尔会在另一个应用程序中收到错误消息"#40001 Deadlock found when restarting“。在阅读了MySQL应对此问题的提示后,他们建议重试事务。我的问题是知道在Delphi中做这件事的最好方法。我正在做这个:

代码语言:javascript
复制
transaction_completed_ok:= False;
repeat
  try
    my_db.StartTransaction;
    (... do the inserts)
    my_db.Commit;
    transaction_completed_ok:= True;
  except
    my_db.Rollback;
    Sleep(1000);
  end;
until transaction_completed_ok;

在两个应用程序上对每个事务执行此操作,是处理问题的有效方法吗?有人能分享一个最好的方法吗?欢迎任何帮助。

EN

回答 1

Stack Overflow用户

发布于 2013-07-25 20:51:02

您用于在出错时重新启动事务的代码无法解决问题,因为重新执行一个相同的代码将导致相同的错误。例如,如果您的代码导致唯一性冲突,应用程序将被卡住。为了解决这个问题,您应该重新组织应用程序逻辑,以避免死锁。当两个并行连接试图以不同的顺序锁定两个表时,就会发生死锁,例如:

代码语言:javascript
复制
connection1 locks tableA;
connection2 locks tableB;
connection1 attempts to lock tableB - waits for connection2 to unlock tableB;
connection2 attempts to lock tableA - waits for connection1 to unlock tableA.

结果,我们得到了一个死锁。为了避免死锁,您应该为两个连接设置相同的表锁定顺序,例如:

代码语言:javascript
复制
connection1 locks tableA;
connection2 locks tableA;
connection1 locks tableB;
connection2 locks tableB.

您可以在http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html上阅读有关死锁的更多信息

要解决此问题,您可以使用以下算法:

代码语言:javascript
复制
  isLocked := False;

  while not isLocked do
  try
    < explicit lock tableA >
    < explicit lock tableB >
    isLocked := True;
  except
    < explicit unlock tableA >
    < explicit unlock tableB >
  end;

  if isLocked then
  try
    < do inserting to tableA and tableB >
  finally
    < explicit unlock tableA >
    < explicit unlock tableB >
  end;
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17843982

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档