tags:

views:

86

answers:

4

I am trying to copy one table over another one "atomically". Basically I want to update a table periodically, such that a process that reads from the table will not get an incomplete result if another process is updating the table.

To give some background info, I want a table that acts as a leaderboard for a game. This leaderboard will update every few minutes via a separate process. My thinking is as follows:

Table SCORES contains the publicly-viewable leaderboard that will be read from when a user views the leaderboard. This table is updated every few minutes. The process that updates the leaderboard will create a SCORES_TEMP table that contains the new leaderboard. Once that table is created, I want to copy all of its contents over to SCORES "atomically". I think what I want to do is something like:

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

I want to replace everything in SCORES. I don't need to maintain my primary keys or auto increment values. I just want to bring in all the data from SCORES_TEMP. But I know that if someone views the scores before these 2 statements are done, the leaderboard will be blank. How can I do this atomically, such that it will never show blank or incomplete data? Thanks!

+2  A: 

In MySQL, because of the behavior of TRUNCATE I think you'll need to:

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

I'm not sure there's a way to make what is always effectively a DDL operation transaction safe.

Cade Roux
What is a "DDL operation"? Thanks...
ZenBlender
DDL = data definition language - things like CREATE TABLE, etc.
Cade Roux
A: 

I don't know hot MySQL deals with transaction, but in T-SQL you could write

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

This way your operation would be "atomic", but not instantaneous.

Paulo Santos
+1  A: 

You may use transactions (for InnoDB),

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

or LOCK TABLES (for MyISAM):

LOCK TABLES;
DELETE FROM SCORES;
INSERT INTO SCORES SELECT * FROM SCORES_TEMP;
UNLOCK TABLES;
Quassnoi
+2  A: 

Use rename table

RENAME TABLE old_table TO backup_table, new_table TO old_table;

It's atomic, works on all storage engines, and doesn't have to rebuild the indexes.

Todd Gardner
Transactions will definitely help now that I know they can accomplish the atomic needs that I have, but for simplicity, this table renaming solution is the best for this particular situation. Thanks everyone!
ZenBlender