Блог Александра Башкирова

ИТ и бизнес, компьютеры и ПО, фото, программирование и просто мысли…
Этот сайт в основном посвящен тому, что мне интересно вне работы. Ведется в порядке хобби.
Все изложенное на сайте - мое частное оценочное мнение и не может быть истолковано иначе.
Со всеми вытекающими из этого последствиями.

Про блокировки таблиц в mysql

Просмотров: 3179Комментарии: 0
Alib.spb.ru

Натолкнулся на любопытную особенность работы блокировки в mysql. Итак дано:

таблица table-1 и table-2. Из второй мы читаем, результат записываем в первую. Но читаем не просто - а достаточно хитро, примерно так

TRUNCATE TABLE table-1;
INSERT INTO table-1 SELECT * FROM table-2 WHERE flf2=(SELECT fld FROM table-2 WHERE fld3='value');

Если таблицы не заблокировать (что мне понятнее) или не использовать транзаккцию (что для случая mysql я пока не использовал), то при одновременном выполнении запроса получится ... да всё, что угодно. Имитация (запуск скрипта с вызовом указанного кода в несколько потоков) приводил к тому, например, что для ряда ситуаций число строк в table-1 превышало ожиждаемое в 1,5-2 раза.

Соответственно, требуется обернуть вызовы блокировкой. Которая по идее должна выглядеть так:

LOCK TABLES table-1 WRITE, table-2 READ;
TRUNCATE TABLE table-1;
INSERT INTO table-1 SELECT * FROM table-2 WHERE flf2=(SELECT fld FROM table-2 WHERE fld3='value');
UNLOCK TABLES;

Но вот фигушки. В такой конструкции mysql упорно выдает ошибку ERROR #1100: Table 'table-2' was not locked with LOCK TABLES

Как оказалось, это не бага, это фича. Как написано в документации https://dev.mysql.com/doc/refman/5.7/en/lock-tables.html - для каждого упоминения таблицы table-2 в SELECT требуется свой блокировочный алиас в LOCK'е. Вот так примерно:

LOCK TABLES table-1 WRITE, table-2 READ, table-2 AS t2 READ;
TRUNCATE TABLE table-1;
INSERT INTO table-1 SELECT * FROM table-2 WHERE flf2=(SELECT fld FROM table-2 AS t2 WHERE fld3='value');
UNLOCK TABLES;

В такой конструкции - всё будет работать.

И еще момент: когда используем LOCK TABLES, то в нем надо перечислить (заблокировать) все таблицы, к которым будет доступ на чтение / запись. В противном случае mysql выдаст Error #1100. Ту самую, что какая-то таблица не блокирована, ага.

Оставьте комментарий!


Комментарий будет опубликован после проверки

     

  

(обязательно)