将表迁移到新模式时,我希望确保使用复制和重命名过程将原子切换到新表。因此,我试图重命名这样一个锁定的表:
CREATE TABLE foo_new (...)
-- copy data to new table, might take very long
INSERT INTO foo_new (id,created_at,modified_at)
SELECT * FROM foo WHERE id <= 3;
LOCK TABLES foo WRITE, foo_new WRITE;
-- quickly copy the tiny rest over
INSERT INTO foo_new (id,created_at,modified_at)
SELECT * FROM foo WHERE id > 3;
-- now switch to the new table
RENAME TABLE foo TO foo_old, foo_new TO foo;
UNLOCK TABLES;
不幸的是,这会产生ERROR 1192 (HY000): Can't execute the given command because you have active locked tables or an active transaction
。
如何以不同方式完成这项工作?
这是mariadb:10.1
。
答案 0 :(得分:7)
虽然一般来说Rick使用Percona工具是正确的(请参阅1和2),但问题的答案实际上是使用JSON.parse(escaped_query_string_from_db)
。我认为ALTER TABLE
只是一个别名 - 但是it seems like that's not the case。
测试似乎表明这个工作正常:
RENAME
答案 1 :(得分:1)
你可以这样做:
CREATE TABLE foo_old (...)
LOCK TABLES foo WRITE;
INSERT INTO foo_old (id,created_at,modified_at)
SELECT * FROM foo;
DELETE FROM foo WHERE id <= 3;
UNLOCK TABLES;
正如错误消息所述,在锁定相同表时,您无法使用RENAME TABLE
。
答案 2 :(得分:0)
不要重新发明轮子......使用Percona&#39; s pt-online-schema-change
;它负责细节。
答案 3 :(得分:0)
“在LOCK和UNLOCK STATEMENT之间不应写入或读取任何数据。”
我遇到了同样的问题,并在MySQL文档中找到了原因:
As of MySQL 8.0.13, you can rename tables locked with a LOCK TABLES statement, provided that they are locked with a WRITE lock or are the product of renaming WRITE-locked tables from earlier steps in a multiple-table rename operation.
To execute RENAME TABLE, there must be no active transactions or tables locked with LOCK TABLES.
顺便说一句,在MySQL 5.7中,当表被“ LOCK table tbl WRITE”语句锁定时, 由于执行了“ ALTER TABLE tbl_0 RENAME TO tbl_1”,该锁将被释放。 并且在同一会话和新会话中会发生奇怪的行为。
# MySQL 5.7
# session 0
mysql> lock tables tbl_0 WRITE;
Query OK, 0 rows affected (0.02 sec)
mysql> ALTER TABLE tbl_0 RENAME TO tbl_1;
Query OK, 0 rows affected (0.02 sec)
mysql> select * from tbl_1;
ERROR 1100 (HY000): Table 'tbl_1' was not locked with LOCK TABLES
# then start new session
# session 1
mysql> select * from tbl_1;
...
1 row in set (0.01 sec)
# session 0
mysql> unlock tables;
希望它会有所帮助。