2013-07-24 4 views
1

Я использую UniDAC (Devart) в 2 приложениях, обращающихся к базе данных MySQL. Во время некоторых крупных операций обновления обновлений, выполненных одним приложением, иногда я получаю сообщение об ошибке «# 40001« Тупик », обнаруженный при попытке блокировки, попробуйте перезапустить транзакцию» в другой. Прочитав советы MySQL, чтобы справиться с этим, они говорят, чтобы повторить транзакцию. Мой вопрос состоит в том, чтобы узнать, как это сделать в Delphi. Я делаю это:Избегайте взаимоблокировок MySQL/UniDAC/Delphi

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 это каждую сделку, на обоих приложениях, является верным способом для решения проблемы? Может ли кто-нибудь поделиться наилучшим образом? Любая помощь приветствуется.

+1

Нет необходимости 'Sleep()', так как замки уже были приобретены конкурирующей сделки, и поэтому сразу же повторить попытку это один заставит его ждать на получение блокировки, а не тупик. Кроме того, вы, вероятно, захотите проверить причину, по которой транзакция завершилась неудачно, так как вы, вероятно, захотите обработать условия, отличные от тупика, по-разному. – eggyal

ответ

2

Ваш код для перезапуска транзакции при ошибке не может решить проблему, так как повторное выполнение одного и того же кода вызовет те же ошибки. Например, если ваш код вызывает нарушение уникальности, приложение застрянет. Чтобы решить проблему, вы должны реорганизовать логику приложения, чтобы избежать взаимоблокировки. Тупик возникает, когда два параллельных соединений пытаются заблокировать 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. 

В результате, мы получаем тупиковую ситуацию. Для того, чтобы избежать тупиковой ситуации, вы должны установить тот же порядок блокировки таблицы для обоих соединений, например:

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

Вы можете прочитать более подробную информацию о тупиковой ситуации в http://dev.mysql.com/doc/refman/5.1/en/innodb-deadlocks.html

Чтобы решить эту проблему, вы можете использовать следующие алгоритм:

+0

Это не поможет, если вы используете 2 разных соединения в двух разных приложениях, если только вы не свяжете их между собой. –

Смежные вопросы