我在模式(
my_table
)上有一个表(db1
),我正试图迁移到同一服务器上的另一个模式(db2
)。为此,我在 db1
上创建了一个触发器,用于插入、更新和删除到 my_table
,这实际上将操作复制到 db2.my_table
。一切都在开发中运行良好,但我们有一个奇怪的设置,其中这两个模式位于不同的 docker 图像上以用于迁移目的。所以db1
在一个容器上,db2
在另一个容器上,两个不同的mysql服务器实例。
这会导致本地复制触发器出现问题,因此我在其中添加了一个
IF
子句,以确保 db2
在触发之前存在于服务器上。例如,这里是 AFTER INSERT
触发器:
create trigger insert_my_table
after INSERT
on db1.my_table
for each row
begin
IF
(SELECT EXISTS(SELECT SCHEMA_NAME
FROM INFORMATION_SCHEMA.SCHEMATA
WHERE SCHEMA_NAME = 'db2')) THEN
insert into db2.my_table
select *
from db1.my_table ff
where ff.id = NEW.id
on duplicate key update db2.my_table.id=NEW.id;
END IF;
end;
现在我可以毫无问题地在本地
my_table
中插入新行。但是如果我在插入之前尝试锁定表格(例如mysqldump
):
lock tables `my_table` write;
insert into my_table (id, name, description) value (1, 'test', 'test_desc');
然后我得到这个错误
"ERROR 1100 (HY000): Table 'my_table' was not locked with LOCK TABLES"
什么给?有什么我忘记了吗?
我认为问题在于,一旦您锁定了会话中的任何表,该会话就只能访问已为其明确锁定的表。由于您在
my_table
中写信给db2
,因此您也必须将其锁定。
MySQL锁表
重要的是:
需要锁的会话必须获取它需要的所有锁 在单个 LOCK TABLES 语句中。虽然由此获得的锁是 held,会话只能访问锁定的表。例如,在 以下语句序列,尝试发生错误 访问 t2 因为它没有在 LOCK TABLES 语句中锁定:
mysql> LOCK TABLES t1 READ;
mysql> SELECT COUNT(*) FROM t1;
+----------+
| COUNT(*) |
+----------+
| 3 |
+----------+
mysql> SELECT COUNT(*) FROM t2;
ERROR 1100 (HY000): Table 't2' was not locked with LOCK TABLES
INFORMATION_SCHEMA 数据库中的表是一个例外。即使会话持有通过 LOCK TABLES 获得的表锁,也可以在不显式锁定的情况下访问它们。