我们有一个使用MySQL数据库的在线系统。 我们需要将较旧的备份数据库(完整表,而不是转储文件)与当前数据库合并。 没有遇到任何服务器停机时间,你会怎么做? 请注意,该系统24/7在线。 有什么问题可能会上升?
谢谢。
当弄乱MySQL的文件系统时,你必须停止MySQL服务器。 为避免在线机器停机,请使用具有MySQL服务器的SAME版本的备份/虚拟化机器。 当BACKUP MySQL服务器停止时,将表(我假设.RRM,.MYI等?)复制到/ var / lib / mysql / BACKUP_DB(BACKUP_DB的相应目录)中的文件系统中。
启动BACKUP MySQL服务器,并确保使用脚本或CLI正确加载数据。 validation后,mysqldump BACKUP_DB数据库,以便将其加载到活动服务器中:
mysqldump --extended-insert BACKUP_DB > /root/sql/BACKUP_DB.sql
现在,您已经将原始备份数据转换为可以在无需停机的情况下加载到MySQL中的SQL语句(与原始数据不同)。 将BACKUP_DB.sql移到活动机器上。
将BACKUP_DB.sql作为不同的数据库导入到您的LIVE MySQL实例中:
mysql BACKUP_DB < /root/sql/BACKUP_DB.sql
你现在应该把备份数据库加载到MySQL中作为BACKUP_DB。
现在,依赖INSERT IGNORE或REPLACE INTO语句(是否覆盖旧数据或填充索引中的空白):
mysqldump --no-create-db --no-create-info --extended-insert --insert-ignore MERGE_SOURCE | mysql BACKUP_DB
或者,对于REPLACE INTO操作:
mysqldump --no-create-db --no-create-info --extended-insert MERGE_SOURCE | sed 's/INSERT INTO/REPLACE INTO/g' | mysql BACKUP_DB
或者,不要将输出重新input到MySQL,而是发送到文件并查看SQL语句。
mysqldump --no-create-db --no-create-info --extended-insert --insert-ignore MERGE_SOURCE > /root/sql/merge.sql mysqldump --no-create-db --no-create-info --extended-insert MERGE_SOURCE | sed 's/INSERT INTO/REPLACE INTO/g' > /root/sql/merge.sql
最后,为了避免宕机,在第二个数据库上转储第一个数据库:
mysqldump BACKUP_DB | mysql CURRENT_DB
您可以总是先locking数据库,以防止数据被写入(例如)z表中,并在表中有一个外键(已经被写入):
FLUSH TABLES WITH READ LOCK;
(按上一步执行转储)
UNLOCK TABLES;
将FLUSH命令添加到转储.sql文件的开始并将UNLOCK结束。
在这种情况下,一定要四倍检查您的数据库名称! 询问你不确定的任何后续问题,因为这是高风险的数据混合的东西。 在可能的情况下执行(并详细说明)开发服务器上所需的确切步骤,或虚拟化testing,或创build小规模testing。 只是testing。 而且,当然,需要足够的备份来覆盖每个数据丢失的可能性。
在这个例子中,我们假设你的数据库被称为“zig”,你的备份数据库被称为“zig_backup”。 我还会假设你的备份数据库和你的实时数据库有相同的模式。
我还会假设你的实时数据库不断更新,你不能执行“脱机”合并,然后翻转开关,使合并后的副本“活着”。
需要注意的问题是:
更新过程需要规划哪些表先合并,哪些合并最后。 我一般倾向于先举重(大桌子),然后在小桌子上工作。 根据您的数据大小,这可能无关紧要。
合并的过程将是:
最安全的方法是做一个全表连接,只插入不匹配的行:
for each table in the "live" database: INSERT INTO zig.$table SELECT BACKUP.* FROM zig_backup.$table AS BACKUP LEFT OUTER JOIN zig.$table AS LIVE ON LIVE.ID=BACKUP.ID WHERE LIVE.ID IS NULL;
当然,这需要了解每个表的主键。 直接的“REPLACE”可能不起作用,因为实时数据库中的行可能已经更改,其更改的数据将被
要合并缺失的表,请执行
\u zig_backup SHOW TABLES
要获取所有表的列表,并确定该表是否存在于实时数据库中,可以执行:
\u zig SHOW TABLES LIKE 'tablename';
或者,备份数据库中不存在于“实时”数据库中的表可以二进制复制到实时数据库目录中。
最后,从“实时”数据库中处理删除操作是非常困难的,尤其是因为您正在合并由于某种原因丢失了一些数据。
设置复制并在准备就绪时将DB服务器切换到从服务器,并经过良好testing(!!!)。
除非你有一些技术上的限制,否则这只是一个有效的变体(我的意思是你应该能够在把它们放到24/7的环境中之前进行testing)。
假设你有磁盘空间,我会设置一个迁移数据库,并将数据复制/合并到它。 设置您的Web环境的副本以连接到迁移数据库并进行彻底testing。 然后,一旦开心,在生产环境中更改连接string以查看新的迁移数据库。
您可以使用mysqldump的-T选项来获取表格输出为制表符分隔值。 然后,像凯尔build议的那样创build一个活的数据库的副本。 然后使用mysqlimport将数据重新导入到live-copy并在那里进行testing。 当你准备好从现场切换到现场复制时,你需要停机一段时间。
我没有尝试这个自己,所以警惕Emptor 。