repeat
copy oldest 100 rows that haven't been copied yet to new table
sleep for as long as that update took
until there are <100 rows unprocessed
stop logging service
move the last few rows
rename tables
restart logging
delete the old table when you are sure the conversion has worked
这应该确保转换不会占用服务器容量的一半以上,即使考虑到系统使用随时间变化而施加的负载差异。
或者,如果您想在服务相对空闲但在数据库需要为其用户做一些工作时退出(可能暂停相当长的时间)时尽可能多地使用时间,请替换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>可能是相同的值,尽管在这样的控件中通常会有差异,因此您的进程不会继续启动然后立即暂停,因为它自己的重新启动会对负载测量产生影响。
创建一个 Master-Master 设置,如下所示:
logTable
logTable_new
为 innodbINSERT INTO logTable_new SELECT * FROM logTable
在 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 步,因为它不应该阻塞正常的日志记录。