2013-09-20 2 views
2

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

В довольно загруженной БД MySQL у меня есть таблица access_log, которая получает около 10 миллионов записей в день. Цель состоит в том, чтобы получить вчерашние записи и переместить их в другую БД на другом сервере. Есть ли способ создать резервную копию только вчерашних данных только из этой таблицы?

Спасибо за ваш вклад, Кейт

ответ

1

Учитывая, что у вас есть только одна таблица access_log, просто выбрать эти записи. Вам придется вытащить их в клиентскую программу, а затем подтолкнуть их к другой таблице.

SELECT * 
    FROM access_log 
WHERE logtime >= CURRENT_DATE() - INTERVAL 1 DAY 
    AND logtime < CURRENT_DATE(); 

Тогда

DELETE 
    FROM access_log 
WHERE logtime >= CURRENT_DATE() - INTERVAL 1 DAY 
    AND logtime < CURRENT_DATE(); 

(Избегайте использования BETWEEN для выбора диапазонов времени/даты;. Он делает неправильные вещи в конце диапазона вы выбираете)

Но это немного свинья. Во-первых, эта таблица должна использовать механизм хранения MyISAM, а не InnoDB, поэтому вы не обременены транзакционными издержками.

Если это InnoDB, и вы не можете изменить это, вам может потребоваться написать программу для чтения, а затем удалить данные в более мелкие куски. Например, один из фрагментов может быть:

SELECT * 
    FROM access_log 
WHERE logtime >= CURRENT_DATE() - INTERVAL 1 DAY + INTERVAL 1 HOUR 
    AND logtime < CURRENT_DATE() - INTERVAL 1 DAY + INTERVAL 2 HOUR 

Или, если вы можете позволить себе второй или два простоя в полночь вы можете переименовать таблицу access_log в yesterday_access_log, и создать новую на сегодняшний день. Затем вы можете сэкономить вчерашний стол, не сталкиваясь с производительностью.

Вы можете сделать эту операцию в полночь лог-своп с суждениями типа:

CREATE TABLE `access_log_new` (
    /* whatever columns you have in your access_log table, I made this stuff up */ 
    `log_id` INT(11) NOT NULL AUTO_INCREMENT, 
    `item` VARCHAR(255) NOT NULL, 
    `logtime` TIMESTAMP NOT NULL , 
    PRIMARY KEY (`log_id`) 
) ENGINE=MYISAM; 
DROP TABLE access_log_old; 
RENAME TABLE access_log TO access_log_old; 
RENAME TABLE access_log_new TO access_log; 

Два последних утверждения здесь, то RENAME TABLE заявления, очень быстро. Крошечный период времени, когда нет таблицы access_log, но это намного меньше секунды. Идея заключается в том, чтобы все хорошо настроить, а затем быстро перевернуть файлы журнала.

Это может быть действительно хорошая стратегия; это позволит вам использовать механизм хранения ARCHIVE с дешевой записью и дорогостоящим поиском для вашей таблицы live access_log.

Если у вас есть выбор для реструктуризации вашей таблицы access_log, вы можете разделить его на день, чтобы вы могли просто поменять ежедневные таблицы разделов. Но это более длинная тема.

+0

Олли, спасибо за ваш вклад и дополнительные идеи ... Мне нравится концепция разделения таблицы на день. Я действительно рассматривал использование двух таблиц, но я не могу позволить себе время простоя (в течение некоторого времени в течение дня происходит замедление, но я все равно потеряю тысячи записей); Я также подумал об обмене между таблицами _0 и _1 на основе даты mod "(time()/(24 * 60 * 60))% 2", однако это также было бы свингом производительности, но на стороне веб-сервера (проверьте мод с каждой вставкой). – Kate

+0

WHERE logtime> = CURRENT_DATE() - INTERVAL 1 DAY И logtime AdrianBR

+0

Это не эквивалентное выражение, @AdrianBR, если только сравниваемый столбец «date» не имеет времени, кроме полночь в нем. Если вы имеете в виду 'DATE (logtime)' использование функции, это приведет к победе над использованием индекса в столбце 'logtime', что плохо в большой таблице. –

0
SELECT rows 
INTO OUTFILE '/tmp/backup.txt' 
    FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
    LINES TERMINATED BY '\n' 
    FROM test_table WHERE date=curdate()-1; 

, если у вас нет даты, рассмотреть вопрос о предоставлении им автоматического инкрементного идентификатор и разделить по идентификатору

+0

Я боюсь, что предложение WHERE, которое вы предлагаете, не будет работать, если столбец 'date' - это метка времени. –

+0

, где дата (временная метка) = curdate() - 1 – AdrianBR

Смежные вопросы