Таблицы блокировки MySQL игнорируются - PullRequest
0 голосов
/ 06 сентября 2018

Я обнаружил странную проблему с блокировками таблиц MySQL с помощью движка MyISAM.

Допустим, у меня есть такой код:

LOCK TABLES t1 WRITE;
SELECT SQL_NO_CACHE val1 FROM t1 WHERE something; // val1 = old
// some conditions on val1 and logic
UPDATE t1 SET val1 = new WHERE something;
UNLOCK TABLES;

Насколько я знаю, это должно предотвратить любые одновременные обновления. Но это не так. Иногда он просто игнорирует блокировку и «старый» читается в val1 после того, как другой поток изменил его на «новый». Я даже использую SQL_NO_CACHE, чтобы предотвратить получение старых данных по ошибке.

Почему это? Как я могу предотвратить обновление гонки?

Спасибо.

MySQL 5.5.28, MyISAM, PHP 5.2, расширение mysql_ (устарело, но в устаревшем проекте)

Edit:

ОК, это не должно происходить в чистом SQL, поэтому есть код PHP:

<?php
$conn = mysql_connect(...);

...

mysql_query("LOCK TABLES t1, t2 WRITE"); //t2 also used
$result = mysql_fetch_array(mysql_query("SELECT last_user, ... FROM t1 WHERE id = XXX"));

if($result["last_user"] != $session_user) { //is last activity from another than current user?
 DoStuffWithUser(...); //custom function which uses t2 table
 mysql_query("UPDATE t1 SET last_user = ".$session_user." WHERE id = XXX");
}

mysql_query("UNLOCK TABLES");
...
?>

В результате DoStuffWithUser () вызывается более одного раза для текущего пользователя.

Нет специальных приложений, драйверов, фреймворков. Просто встроенные функции PHP.

Похоже, что проблема в основном (я не могу быть уверен, если исключительно), когда ОДИН пользователь выполняет действие несколько раз - двойной щелчок, некоторый сбой сети, что угодно.

1 Ответ

0 голосов
/ 08 сентября 2018

ОК, это моя песня сегодня https://www.youtube.com/watch?v=48rz8udZBmQ

Большое спасибо @Solarflare за то, что подтолкнул меня на правильный путь.

ОК, где-то есть ошибка, давайте ее найдем. Первая строка, простой запрос блокировки, проверять нечего, это так очевидно ... Ой, подождите ...

LOCK TABLES t1 **WRITE**, t2 WRITE

В каждой таблице должен быть установлен тип блокировки:)

...