Какие таблицы блокируются при добавлении внешнего ключа через миграцию? - PullRequest
1 голос
/ 02 июня 2019

Я добавляю внешний ключ в существующую таблицу MYSQL.Допустим, у меня есть таблица продаж и таблица продуктов.Я добавляю FK в свою таблицу продаж:

ALTER TABLE sales ADD CONSTRAINT sales_product_item_fk FOREIGN KEY (product_id)  REFERENCES products(id) ON DELETE RESTRICT  ON UPDATE RESTRICT

Какие таблицы будут заблокированы во время работы?продажи, продукты, оба?

(отредактировано, чтобы указать MYSQL согласно комментарию ниже)

1 Ответ

0 голосов
/ 02 июня 2019

Обе таблицы будут заблокированы с помощью ОБЩЕЙ блокировки. Это позволяет запускать 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.

Неа. Изменение уровня блокировки ограничено типом изменения, которое вы запрашиваете.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...