Мертвая блокировка возврата MySQL со строкой вставки и FK заблокирована 'для обновления'

Я получаю ошибку мертвой блокировки в своей mysql транзакции.

Простой пример моей ситуации:

Thread1 > BEGIN;
Query OK, 0 rows affected (0.00 sec)

Thread1 > SELECT * FROM A WHERE ID=1000 FOR UPDATE;
1 row in set (0.00 sec)

Thread2 > BEGIN;
Query OK, 0 rows affected (0.00 sec)

Thread2 > INSERT INTO B (AID, NAME) VALUES (1000, 'Hello world');
[Hangs]

Thread1 > INSERT INTO B (AID, NAME) VALUES (1000, 'Hello world2');
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Thread2 >
Query OK, 1 row affected (10.00 sec)

B.AID является FOREIGN KEY, относящимся к A.ID

Я вижу три решения:

  1. зафиксируйте ошибку мертвой блокировки в коде и повторите запрос.
  2. используйте innodb_locks_unsafe_for_binlog в my.cnf
  3. блокировка (для обновления) таблица A в Thread2 прежде вставляет

Есть ли какие-либо другие решения?

7
задан user306814 2 April 2010 в 08:14
поделиться

2 ответа

На основе функции из блога о высокой производительности mysql.

Мне удалось реализовать следующий код обработки тупиковых ситуаций в PHP:

/* maximum number of attempts for deadlock */
$MAX_ATTEMPS = 20;

 /* query */
 $sql = "INSERT INTO B (AID, NAME) VALUES (1000, 'Hello world')"; 

 /* current attempt counter */
 $current = 0;

 /* try to query */
 while ($current++ <$MAX_ATTEMPS) 
 {
     $result = mysql_query($sql);
     if(!$result && ( mysql_errno== '1205' || mysql_errno == '1213'  ) )
         continue;
     else
         break;
 }  
 }

Надеюсь, это может дать вам несколько хороших идей.

0
ответ дан 7 December 2019 в 20:35
поделиться

Я не знаю, какой код окружает эти примеры, но, возможно, стоит использовать LOCK IN SHARE MODE для обоих потоков, поскольку вы фактически не обновляете саму строку. Если вы должны использовать LOCK FOR UPDATE , я бы подумал, что блокировка другого потока будет единственным логическим путем.

Также, если вы готовы отказаться от MySQL, я обнаружил, что PostgreSQL имеет гораздо лучшее разрешение тупиковых ситуаций. В некоторых случаях я обнаруживал, что MySQL зависает каждый раз при запуске одного и того же скрипта в> 1 потоке. Если один и тот же сценарий в PostgreSQL может отлично справиться с любым количеством параллельных потоков.

1
ответ дан 7 December 2019 в 20:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: