更新MySQL数据库

我们有一个使用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”。 我还会假设你的备份数据库和你的实时数据库有相同的模式。

我还会假设你的实时数据库不断更新,你不能执行“脱机”合并,然后翻转开关,使合并后的副本“活着”。

需要注意的问题是:

  • 由于某种原因,旧/新的索引或主键可能会发生冲突(通常如果发生错误或logging意外丢失)
  • 自备份以来发生的删除不应该被“合并”

更新过程需要规划哪些表先合并,哪些合并最后。 我一般倾向于先举重(大桌子),然后在小桌子上工作。 根据您的数据大小,这可能无关紧要。

合并的过程将是:

  1. 使用修改后的数据库名称(例如“zig_backup”)还原实时数据库旁边的备份数据库
  2. 对于活动数据库中的每个表,从备份数据库进行合并
  3. 对于备份数据库中的每个表,检查该表是否存在于实时数据库中,如果不存在,则添加它。

最安全的方法是做一个全表连接,只插入不匹配的行:

 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