MySQL数据库拆分操作步骤
随着业务发展, 混合部署在同一个实例的不同业务库需要拆分 …
MySQL数据库拆分操作步骤
背景:
随着业务发展, 混合部署在同一个实例的不同业务库需要拆分, 假设是user_db和 order_db, 需要迁移的库为 order_db.
实例环境:
开启gtid, 开启半同步复制 现有数据库主从关系:
ip | port | 角色 | mysql版本 | 所包含数据库 |
---|---|---|---|---|
192.168.1.16 | 3306 | master | 5.7.14 | user_db, order_db |
192.168.2.16 | 3306 | slave | 5.7.14 | user_db, order_db |
拆分后数据库主从关系:
ip | port | 角色 | mysql版本 | 所包含数据库 |
---|---|---|---|---|
192.168.1.16 | 3306 | master | 5.7.14 | user_db |
192.168.2.16 | 3306 | slave | 5.7.14 | user_db |
192.168.1.17 | 3306 | master | 5.7.14 | order_db |
192.168.2.17 | 3306 | slave | 5.7.14 | order_db |
原则:
- 不能出现有两个地方同时写入同一个数据库.
- 不能丢失数据. 如果回滚, 业务切换过程中产生的数据要重新写入原先的主库.
一 准备阶段
安装新的数据库, 执行mysql_auto_install.sh不会执行任何事务(不会初始化用户). 在192.168.1.17和192.168.2.17上分别执行
bash mysql_auto_install.sh -p 3306
- 从192.168.2.16 上用mydumper导出整个数据库,同步到192.168.1.17, 192.168.2.17. 之所以导出全部数据库 是为了同时导出mysql库, 可以不用再次进行授权
mydumper -u xxx -p xxx -S /path/to/mysql.sock -t 8 -o /tmp/backup -c rsync -avzP -e ssh /tmp/backup root@192.168.1.17:/tmp rsync -avzP -e ssh /tmp/backup root@192.168.2.17:/tmp
在192.168.1.17和192.168.2.17上进行myloader导入(不记录binlog),导入完成之后在 ,根据mydumper导出的metedata文件设置gtid_purged, 并执行 flush privileges. tips: 在导入时可以调整 innodb_flush_log_at_trx_commit=0, slow_query_log=0 加快导入速度, 在导入完成之后恢复
myloader -u root -S /path/to/mysql.sock -t 8 -o -d /tmp/backup mysql> set global gtid_purged='5696461f-3bc5-11e8-8529-00163e0261b0:xxx': mysql> flush privileges;
在 192.168.1.17:3306(新maser)上执行change master
mysql> change master to -> MASTER_HOST='192.168.1.16', -> master_user='xxx', -> master_password='yyy', -> MASTER_PORT = 3306, -> master_auto_position=1;
在 192.168.2.17:3306(新slave)上执行change master
mysql> change master to -> MASTER_HOST='192.168.1.17', -> master_user='xxx', -> master_password='yyy', -> MASTER_PORT = 3306, -> master_auto_position=1;
二 切换操作阶段
- 业务需要连到新的主库 192.168.1.17:3306. 此时 192.168.1.17:3306 只读, 192.168.1.16:3306可写
在与研发确定的切换时间, 在 192.168.1.16:3306和 192.168.2.16:3306执行rename table操作, 确保没有数据可以写入
mysql> -> select concat( "rename table order_db.",table_name,' to order_db.',table_name,'_rename;' ) from information_schema.tables where table_schema='order_db'; # 生成rename sql -> select concat( "rename table order_db.",table_name,'_rename',' to order_db.',table_name,';') from information_schema.tables where table_schema='order_db'; # 生成回滚rename sql -> rename table order_db.order_db to order_db.order_db_rename; #执行rename 操作
在192.168.1.17:3306(新maser)上执行 stop slave 操作,使用 第2步 生成的sql将表rename回来,并关掉read_only, 使业务可写. 此时 192.168.1.17:3306, 192.168.1.16:3306同时可写, 但是192.168.1.16:3306上 order_db中的表已经rename, 所以无法写入成功, 可以保证只有一个实例可以写入 order_db数据
mysql> stop slave; mysql> rename table order_db.test_rename to order_db.test; #执行rename 操作 mysql> set global read_only=0;
此时需要验证业务是否正常, 如果业务正常, 进行收尾阶段; 如果业务异常, 需要回滚, 按下列步骤进行回滚
- 业务需要连到原来的主库 192.168.1.16:3306
在192.168.1.17:3306上开启只读
mysql> set global read_only=1;
在原来的主库192.168.1.16:3306上, 将order_db的所有可写用户锁定, 并kill掉order_db所有的连接, 确保下一步change master之后, 主从同步完成之前没有连接可以写入数据
mysql> alter user 'xxx_user'@'192.168.%' account lock; mysql> kill pid;
在 192.168.1.16:3306上, 执行change master, 从192.168.1.17:3306(新主库)同步变更到192.168.1.16:3306(老主库)
mysql> change master to -> MASTER_HOST='192.168.1.17', -> master_user='xxx', -> master_password='yyy', -> MASTER_PORT = 3306, -> master_auto_position=1;
同步完成后, 在 192.168.1.16:3306 上stop slave, 并reset slave; 然后解锁用户
mysql> stop slave; mysql> reset slave all; mysql> alter user 'xxx_user'@'192.168.%' account unlock;
在192.168.1.17:3306上重新开启slave, 重新同步数据, 方便下次操作切换
mysql> start slave;
此时回滚完成, 并且没有丢失切换过程中产生的数据, 需要再次验证业务
三 收尾工作
业务切换之后, 测试ok, 需要进行收尾工作
在新主库 192.168.1.17:3306 上执行 reset slave all;
mysql> reset slave all;
在老主库和从库上 192.168.1.16:3306,192.168.2.16:3306 删除已经迁移的库, 谨慎操作
mysql> set sql_log_bin = off; mysql> drop database order_db ;
在新主库和从库 192.168.1.17:3306,192.168.2.17:3306 上将 不需要的数据库删除, 谨慎操作
mysql> set sql_log_bin = off; mysql> drop database user_db ;
四 总结
- 数据库拆分对比数据库迁移的难度在于, 在切换过程操作中, 原主库需要保持一直可写. 而在数据库迁移的过程中, 为确保数据一致性, 可以将原主库置为只读.
- 在数据库拆分收尾阶段需要drop database.drop database是没法回滚的. 建议平时做好冷备, 并且谨慎操作. 否则就要准备删库跑路了