原子地将一个MySQL表复制到另一个表上?

时间:2009-06-01 17:06:58

标签: mysql

我试图将一个表复制到另一个表“原子地”。基本上我想定期更新一个表,这样如果另一个进程正在更新表,那么从表中读取的进程将不会得到不完整的结果。

为了提供一些背景信息,我想要一个充当游戏排行榜的桌子。该排行榜将通过单独的流程每隔几分钟更新一次。我的想法如下:

表格SCORES包含可在公众查看的排行榜,当用户查看排行榜时,该排行榜将被读取。此表每隔几分钟更新一次。更新排行榜的过程将创建包含新排行榜的SCORES_TEMP表。创建该表后,我想将其所有内容“原子地”复制到SCORES。我想我想做的是:

TRUNCATE TABLE SCORES;
INSERT INTO SCORES SELECT * FROM SCORES_TEMP;

我想替换SCORES中的所有内容。我不需要维护主键或自动增量值。我只是想从SCORES_TEMP中获取所有数据。但我知道,如果有人在完成这两个陈述之前查看了分数,那么排行榜将是空白的。我怎样才能原子地做到这一点,以至于它永远不会显示空白或不完整的数据?谢谢!

4 个答案:

答案 0 :(得分:11)

使用rename table

RENAME TABLE old_table TO backup_table, new_table TO old_table;

它是原子的,适用于所有存储引擎,不必重建索引。

答案 1 :(得分:2)

在MySQL中,由于the behavior of TRUNCATE,我认为你需要:

BEGIN TRANSACTION;
DELETE FROM SCORES;
INSERT INTO SCORES SELECT * FROM SCORES_TEMP;
COMMIT TRANSACTION;

我不确定是否有办法让有效的DDL操作事务安全。

答案 2 :(得分:2)

您可以使用交易(InnoDB),

BEGIN TRANSACTION;
DELETE FROM SCORES;
INSERT INTO SCORES SELECT * FROM SCORES_TEMP;
COMMIT;

LOCK TABLES(适用于MyISAM):

LOCK TABLES;
DELETE FROM SCORES;
INSERT INTO SCORES SELECT * FROM SCORES_TEMP;
UNLOCK TABLES;

答案 3 :(得分:0)

我不知道热门的MySQL处理事务,但在T-SQL中你可以编写

BEGIN TRAN
DELETE FROM SCORES
INSERT INTO SCORES SELECT * FROM SCORES_TEMP
COMMIT TRAN

这样你的操作将是“原子的”,但不是瞬间的。