我有一个表,其中包含Mysql服务器中的所有历史数据,并且它非常庞大(大约7亿行)。我正在创建一个具有相同列但具有分区的新表,然后我需要将旧表中的所有数据复制到新的分区表中。我已经有了正确的脚本来做到这一点,但我认为它可能锁定表。我不希望发生这种情况,因为它在生产服务器上。我该怎么办才能避免锁定桌子?
答案 0 :(得分:3)
假设表格具有完全相同的列,您可以执行以下操作:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
INSERT INTO NEW_TABLE (SELECT * FROM OLD_TABLE);
COMMIT ;
我已根据Wistar's评论添加了一些其他说明。这里可以使用的读取级别是:
我希望这会有所帮助。
答案 1 :(得分:0)
我不知道你的剧本是什么,但我建议你插入chucks。 See this example
如果您使用SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
,则可能会插入错误的行版本。如果你用一个选择插入所有行,那么你不仅会有锁,而且它不会是最好的表现。
您可以执行类似
的操作 INSERT INTO NEW TABLE (SELECT * FROM OLD_TABLE LIMIT 1000 OFFSET 0 )
INSERT INTO NEW TABLE (SELECT * FROM OLD_TABLE LIMIT 1000 OFFSET 1000 )
INSERT INTO NEW TABLE (SELECT * FROM OLD_TABLE LIMIT 1000 OFFSET 2000 )
...
CREATE PROCEDURE myproc()
BEGIN
@rows :=0
SELECT COUNT(*) FROM OLD_TABLE into @rows
DECLARE i int DEFAULT 0;
WHILE i <= @rows DO
PREPARE stmt1 FROM 'INSERT INTO NEW TABLE (SELECT * FROM OLD_TABLE LIMIT 1000 OFFSET ? )'
EXECUTE stmt1 USING @i;
DEALLOCATE PREPARE stmt1;
SET i = i + 1000;
END WHILE;
END
当然,您可以通过更改LIMIT
尺寸
答案 2 :(得分:0)
以块的形式复制。你有MyUser
AUTO_INCREMENT
吗?如果是,那么
PRIMARY KEY
如果存在大量空白,或者您有其他问题,请参阅other techniques for efficiently chunking。
The evils of Pagination via OFFSET
更好的是,使用Percona的 WHERE id >= $x AND id < $x + 1000
。它完成了我所描述的大部分思考, plus 它允许你在复制完成时写入表。 (它使用pt-online-schema-alter
来实现它。)
答案 3 :(得分:0)
为减少使用docker build --network=host -t image_name .
的弊端,this article描述了一种在数字主键OFFSET
可用时强制使用JOIN
的可能方法。适当的索引。请注意,为了跟踪过程,将创建“ procedure_log”表,并在处理批处理后逐步对其进行更新:
对于MySQL:
id