Атомное копирование одной таблицы MySQL поверх другой? - PullRequest
8 голосов
/ 01 июня 2009

Я пытаюсь скопировать одну таблицу поверх другой "атомарно". По сути, я хочу периодически обновлять таблицу, чтобы процесс, который читает из таблицы, не получил неполный результат, если другой процесс обновляет таблицу.

Чтобы дать некоторую справочную информацию, я хочу таблицу, которая выступает в качестве таблицы лидеров для игры. Этот список лидеров будет обновляться каждые несколько минут через отдельный процесс. Мое мышление таково:

Таблица SCORES содержит общедоступную таблицу лидеров, которая будет считываться, когда пользователь просматривает таблицу лидеров. Эта таблица обновляется каждые несколько минут. Процесс, который обновляет таблицу лидеров, создаст таблицу SCORES_TEMP, которая содержит новую таблицу лидеров. Как только эта таблица создана, я хочу скопировать все ее содержимое в SCORES «атомарно». Я думаю, что я хочу сделать что-то вроде:

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

Я хочу заменить все в СЧЕТАХ. Мне не нужно поддерживать мои первичные ключи или значения автоинкремента. Я просто хочу ввести все данные из SCORES_TEMP. Но я знаю, что если кто-то просматривает результаты до того, как эти 2 утверждения будут сделаны, таблица лидеров будет пустой Как я могу сделать это атомарно, чтобы никогда не показывать пустые или неполные данные? Спасибо!

Ответы [ 4 ]

11 голосов
/ 01 июня 2009

Использовать переименовать таблицу

RENAME TABLE old_table TO backup_table, new_table TO old_table;

Он атомарный, работает на всех механизмах хранения и не должен перестраивать индексы.

2 голосов
/ 01 июня 2009

Вы можете использовать транзакции (для 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;
2 голосов
/ 01 июня 2009

В MySQL из-за поведения TRUNCATE Я думаю, вам нужно:

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

Я не уверен, что есть способ сделать безопасную транзакцию DDL всегда безопасной.

0 голосов
/ 01 июня 2009

Я не знаю, как MySQL работает с транзакциями, но в T-SQL вы могли бы написать

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

Таким образом, ваша операция будет «атомарной», но не мгновенной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...