Обе таблицы будут заблокированы с помощью ОБЩЕЙ блокировки. Это позволяет запускать SELECT для таблиц и выполнять другие операции, для которых требуется блокировка SHARED, но не позволяет выполнять какие-либо действия, требующие блокировки EXCLUSIVE, например UPDATE
.
.
Вы можете подтвердить это: создайте две таблицы sales
и products
и заполните таблицу sales
несколькими миллионами строк, достаточно для того, чтобы сделать ALTER TABLE по крайней мере несколько секунд. Значение product_id может быть одинаковым для каждой строки в этой тестовой таблице.
mysql> select * from sales limit 3;
+----+------------+
| id | product_id |
+----+------------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
...
И убедитесь, что в таблице products
есть строка для соответствия внешнему ключу.
mysql> select * from products;
+----+-----------+
| id | name |
+----+-----------+
| 1 | some name |
+----+-----------+
Теперь откройте два окна и будьте готовы выполнять запросы к таблицам в каждом окне.
Запустите ALTER TABLE, чтобы добавить внешний ключ. Это создаст новый индекс, если для внешнего ключа уже нет индекса. Создание индекса - это то, что занимает больше всего времени. Фактически, даже добавление индекса без внешнего ключа будет демонстрировать такое же поведение блокировки.
mysql> ALTER TABLE sales ADD CONSTRAINT sales_product_item_fk FOREIGN KEY (product_id)
REFERENCES products(id) ON DELETE RESTRICT ON UPDATE RESTRICT;
Это ждет, пока он строит индекс. На моем ноутбуке с 8 миллионами строк это занимает более 30 секунд. Много времени для выполнения запросов во втором окне.
mysql> update sales set product_id = null limit 2;
Блокирует ожидание блокировки некоторых строк в sales
. Вы, вероятно, ожидали этого. Вы не можете обновить таблицу, пока идет построение индекса.
mysql> update products set name = 'othername';
Это также блокирует, ожидая эксклюзивной блокировки строки в products
. Он не может получить эксклюзивную блокировку, пока на столе есть общая блокировка.
Можете ли вы отменить требование о блокировке с помощью предложения LOCK=NONE
?
mysql> ALTER TABLE sales ADD CONSTRAINT sales_product_item_fk FOREIGN KEY (product_id)
REFERENCES products(id) ON DELETE RESTRICT ON UPDATE RESTRICT, LOCK=NONE;
ERROR 1846 (0A000): LOCK=NONE is not supported. Reason: Adding foreign keys needs foreign_key_checks=OFF. Try LOCK=SHARED.
Неа. Изменение уровня блокировки ограничено типом изменения, которое вы запрашиваете.