我正在向现有的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)
答案 0 :(得分:0)
两个表都将使用SHARED锁锁定。这允许您对表运行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;
正在等待建立索引。在我的笔记本电脑上,有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.
不。更改锁定级别受您请求的更改类型的限制。