通过迁移添加外键时,哪些表被锁定?

时间:2019-06-02 16:38:00

标签: mysql sql foreign-keys

我正在向现有的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 :(得分:0)

两个表都将使用SHARED锁锁定。这允许您对表运行SELECT,并允许您执行其他需要SHARED锁定的操作,但不允许您执行任何需要EXCLUSIVE锁定的操作,例如UPDATE

您可以确认以下内容:创建两个表salesproducts,并用几百万行填充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;

正在等待建立索引。在我的笔记本电脑上,有800万行,耗时超过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.

不。更改锁定级别受您请求的更改类型的限制。