简体   繁体   English

避免死锁MySQL / UniDAC / Delphi

[英]Avoid deadlocks MySQL/UniDAC/Delphi

I'm using UniDAC (Devart) in 2 applications accessing a MySQL database. 我在2个访问MySQL数据库的应用程序中使用UniDAC(Devart)。 During some heavy update update operations made by one application, occasionally I get an Error "#40001 Deadlock found when trying to get lock; try restarting transaction" in the other. 在一个应用程序进行的大量更新操作中,有时在另一个应用程序中收到错误消息“#40001尝试获取锁时发现死锁;尝试重新启动事务”。 Having read MySQL tips to cope with this, they say to retry the transaction. 阅读了MySQL技巧以解决此问题后,他们说要重试该事务。 My question is to know the best way to do this in Delphi. 我的问题是知道在Delphi中执行此操作的最佳方法。 I'm doing this: 我正在这样做:

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;

Doing this to every transaction, on both apps, is a valid way to deal with problem? 在两个应用程序上对每笔交易都这样做,是解决问题的有效方法吗? Can anyone share a best way? 谁能分享最好的方法? Any help is welcome. 欢迎任何帮助。

Your code for restarting transaction on error cannot solve the problem, since re-execution of one and the same code will cause the same errors. 由于错误而重新执行事务的代码无法解决该问题,因为重新执行一个相同的代码将导致相同的错误。 For example, if your code causes uniqueness violation, the application will get stuck. 例如,如果您的代码导致违反唯一性,则应用程序将被卡住。 To solve the problem, you should reorganize the application logic, in order to avoid a deadlock. 为了解决该问题,您应该重新组织应用程序逻辑,以避免死锁。 A deadlock occurs when two parallel connections attempt to lock 2 tables in a different order, for example: 当两个并行连接尝试以不同顺序锁定2个表时,将发生死锁,例如:

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.

As a result, we get a deadlock. 结果,我们陷入僵局。 To avoid the deadlock, you should set the same table locking order for both connections, for example: 为避免死锁,您应该为两个连接设置相同的表锁定顺序,例如:

connection1 locks tableA;
connection2 locks tableA;
connection1 locks tableB;
connection2 locks tableB.

You can read more information about deadlock at http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html 您可以在http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html上阅读有关死锁的更多信息。

To solve the problem, you can use the following algorithm: 要解决此问题,可以使用以下算法:

  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;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM