Возможно ли (и как) преобразовать огромную таблицу MyISAM в InnoDB, не переводя приложение в автономный режим. Требуется вставлять пару строк в эту таблицу каждую секунду, но можно приостановить ее примерно на 2 минуты.
Очевидно, что ALTER TABLE ... engine = innodb не будет работать. Для этого у меня был план создать новую таблицу с движком innodb и скопировать в нее содержимое. И, наконец, приостановить поток журнала приложения и переименовать таблицу.
К сожалению, даже копирование небольшими партиями по 100 строк приводит к значительному отставанию через некоторое время.
Изменить : существующие строки никогда не изменяются, эта таблица используется для ведения журнала.
Ответы:
Создайте настройку Мастер-Мастер следующим образом:
logTable
logTable_new
как innodbINSERT INTO logTable_new SELECT * FROM logTable
(psuedocode) на MasterB, который отправляет репликацию на MasterAlogTable_new
на MasterA завершит синхронизацию, поменяйте местами таблицыисточник
Учитывая ограничение:
В процессе ведения журнала, если у вас есть какой-то хороший способ установить маркер, чтобы вы могли сказать, с чего вы запускаете процесс, вы можете затем повторно применить любые журналы или записать журналы в текстовый файл, чтобы позже вы можете проглотить их с
LOAD DATA INFILE
Частично проблема заключается в том, что запись небольшими партиями означает, что индексы нужно пересчитывать снова и снова; лучше запустить все сразу, но это может привести к некоторой «заметной» задержке в системе… но вам не нужно делать это на рабочем сервере.
LOAD DATA INFILE
)источник
Добавляете ли вы какую-либо задержку между каждым пакетом или просто пакетируете обновления и запускаете каждый пакет сразу после предыдущего?
Если это так, попробуйте написать сценарий преобразования на вашем любимом языке, например:
Это должно обеспечить, чтобы преобразование не занимало более или менее половины емкости вашего сервера, даже учитывая различия в нагрузке, налагаемой по мере того, как использование системы меняется со временем.
Или, если вы хотите использовать как можно больше времени, когда служба относительно простаивает, но отключается (потенциально может быть приостановлена на длительный период времени), когда базе данных необходимо выполнить некоторую работу для своих пользователей, замените ее
sleep for as long as the update took
наif the server's load is above <upper measure>, sleep for some seconds then check again, loop around the sleep/check until the load drops below <lower measure>
. Это будет означать, что он может двигаться вперед в спокойное время, но полностью остановится, когда сервер занят выполнением своей нормальной рабочей нагрузки. Определение нагрузки будет зависеть от вашей ОС - в Linux и аналогичных значениях средней загрузки за 1 минуту/proc/loadavg
или выходных данныхuptime
.<lower measure>
и<upper measure>
может иметь одинаковое значение, хотя обычно в элементах управления, подобных этому, есть различие, поэтому ваш процесс не продолжает запускаться, а затем сразу приостанавливается из-за того, что его собственный перезапуск влияет на показатель нагрузки.Конечно, это не будет работать для таблиц, где старые строки могут быть изменены, но будет работать нормально для таблицы журнала, подобной той, которую вы описываете.
Вы захотите игнорировать обычную мудрость создания индексов после заполнения новой таблицы в этом случае. Хотя это действительно более эффективно, когда вы хотите, чтобы все было как можно быстрее (проклятие влияет на остальную часть системы), в этом случае вам не нужно большое перенасыщение нагрузки в конце процесса, поскольку индексы полностью создаются за один раз, так как это процесс, который вы не можете приостановить, когда что-то загружается.
источник
Будет ли что-то вроде этой работы?
$auto_increment
таблица журналовmytable
не менялась).$auto_increment
значение, используяSHOW TABLE STATUS LIKE 'mytable'
.CREATE TABLE mytable_new LIKE mytable
ALTER TABLE mytable_new AUTO_INCREMENT=$auto_increment ENGINE=Innodb
RENAME TABLE mytable TO mytable_old, mytable_new TO mytable
INSERT INTO mytable SELECT * FROM mytable_old
,Вы можете выполнить шаг 7 в пакетном режиме или в одном операторе, поскольку он не должен блокировать обычное ведение журнала.
источник