前言
系统运行有很多年了。
数据库服务器也运行很多年了,性能比较老旧,SSD硬盘容量只有250G,在各种需求下,当前服务器的磁盘即将不足。所以开启了本次数据库的迁移行动。
需求
- 迁移的数据量高达130多G, 保证数百万用户的数据安全。
- 不能影响线上正常运行或将影响降到最低
- 保证迁移前后的数据安全与精确还原。
思路
1 .先备份数据
2. 以现有数据库为主数据库搭建从数据库(从主复制)。
3. 检查从数据库数据是否与主数据库完全同步一致
4. 关闭网站,将从数据库切换为主数据库,恢复网站。
实施
为了保险起见,在技术研究过程中,所有的操作先在测试服上跑一遍。
一、备份
第一步就是备份数据,毋庸置疑。涉及到数据库的操作犹如刀尖上的舞者,如果不备份,那么就是成则为仁,败则跑路,多年的数据积累毁于一旦。
如果要备份导出数据库,又不能影响线上数据读写,怎么办?这个时候只能进行热备份。
如何进行热备份?
mysqldump是mysql自带的备份还原工具,它包含很多参数。具体参数了解请转到:
mysqldump参数详解 如果链接失效,自己也可以在网上查一下。
通过使用以下两个参数来进行:
–master-data
–single-transaction
master-data主要使用在主从数据库的master端,该选项将二进制的位置和文件名追加到输出文件中,它会导致全局锁表,使整个数据库不可访问,然后将数据导出来,这显然不满足线上读写的要求,所以master-data一般需要和single-transaction一起使用,single-transaction可以单独开启一个事务,将事务进行隔离,从而互不影响。
但是有个注意事项:
single-transaction只能在InnoDB引擎上生效。
mysql又MYSIAM和InnoDB两种引擎,如果该表或者库不是采用InnoDB引擎,则在导出该表时无法进行事务隔离。
所以当使用mysqldump采用–master-data和–single-transaction两个参数进行热备份时,前提是要开启binlog二进制日志,让mysql的每个操作都写在日志上,然后–single-transaction会进行短暂的全局锁表,把记录mysql当前操作的二进制日志的偏移位置记录下来,然后开启单独的事务进行导出。
有了以上的备份思路,首先将要迁移的数据库开启binlog二进制日志。
1. 开启binlog二进制
vi /etc/my.cnf
设置唯一id
server-id=82
开启二进制
log-bin=mysql-bin
log-bin-index=mysql-bin.index
// 针对的数据库
binlog_do_db=my_database
// 设置单个数据包容量和重做日志大小,根据自己的实际情况设置,尽量大点,这两个参数影响mysqldump能否成功
max_allowed_packet=1024M
innodb_log_file_size = 256M
配好了就重启mysql
service mysqld restart
验证是否开启
show variables like '%log_bin%';
log_bin | ON
show master logs;
mysql-bin.000001 | 120
2. mysqldump备份
我这里使用的命令是:
mysqldump -uMyUser -pMyPassword --hex-blob --force --flush-privileges --max_allowed_packet=1024M
--master-data=2 --single-transaction my_database | gzip > /home/uptry`date +%Y-%m-%d_%H%M%S`.sql.gz
这里做个参数的简单解释:
mysqldump -uMyUser -pMyPassword 这一部分是mysqldump命令和登录mysql的账号密码
--hex-blob 因为我们数据库有BLOB数据,所以要用十六进制转换
--force --flush-privileges 是基本配置
--max_allowed_packet 这个值取决于单个实体数据量大不大,因为我们有BLOB数据,默认的max_allowed_packet不够传输某些实体数据,所以设置大一点,避免造成传输中断,从而备份失败。
--master-data=2 用于记录开始备份时的二进制日志位置,以日志方式存于该备份文件开头。(该操作将会导致锁表操作)
--single-transaction 让备份操作以单独事务运行,保证数据导出时的一致性。这是进行热备份的重要操作。(如果不开启,将会执行master-data锁表操作造成整个数据库阻塞。)
后面的gzip是压缩备份命令。可以节约空间。
我这里操作进行了约2个小时, 时间比较久。如果时间比较久,最好开启linux异步执行,以免当前会话中断。
二、mysql还原
数据备份完成后,被压缩成了20多个G,通过传输工具Multcloud将sql压缩包传输到从服务器后,开启了还原。
解压sql二进制日志包,通过命令可以查看到日志的前50行内有一句:
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000416', MASTER_LOG_POS=116911744;
这个就是告诉我们,该日志保存的是master端文件mysql-bin.000416偏移116911744个字节前的数据。我们到时候做主从同步,只需要从这个位置往后同步就行了。
然后
还原之前先在从服务器上安装好mysql,创建一个和主数据库一样字符类型的库。
然后使用命令:
mysql -uMyUser -pMyPassword my_database < uptry2099-09-19_030001.sql
这个时候就开始还原了。
等待还原结束后,开始搭建master-slave主从同步。
三、 主从搭建
主从搭建还需要配置一下从服务器。
从服务器不需要配置binlog,但是要进行还原配置relay-log。
// 从服务器的唯一id
server-id=91
// 开启relay-log中继日志
relay-log=relay-log
relay-log-index=relay-log.index
binlog是记录mysql的写操作,而relay-log是master-slave之间连接关键的中继日志。
具体原理不在这里赘述。
重启生效
service mysqld restart
授权slave权限账户:
GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO ‘slave账号’@‘slave的ip’ IDENTIFIED BY ‘slave密码’;
连接主从数据库:
change master to master_host='10.248.33.118', master_user='slave账号',
master_password='slave密码', master_log_file='mysql-bin.000416',
master_log_pos=116911744;
让从数据库通过这个账户拉取master端二进制日志,从mysql-bin.000416偏移116911744开始。
查看从数据库状态:
show slave status \G
Slave_IO_Running和Slave_SQL_Running都是Yes才为成功。
聊聊这小节的问题
- Slave_IO_Running是No,但Slave_SQL_Running是Yes。
这多半是change命令有问题,多半是账号密码错误,或者找不到对应的binlog日志。我之前两种情况都遇到过,至于找不到binlog日志,是因为备份还原的消耗时间太久,导致记录的binlog已经过期了。可以通过在master端设置expire_logs_days长一点的时间,这样可以保留时间长一点,但也要注意服务器硬盘空间是否足够。 - slave同步出现异常,提示出现重复的键或者id或者key。
这一情况,可能是由于master端的数据库或者表不是InnoDB引擎,导致热备份时single-transaction事务失效,将当前正在读写的数据也记录到了binlog里面,所以,导出的备份sql里面已经有这个数据了,同步时又拿到了这个数据,导致数据重复。解决方法就是重新备份之前,将该表的引擎修改为InnoDB,注意:修改表的引擎时将会导致锁住该表,出现阻塞。
四、数据检查
如果仅仅是搭建完成主从同步就以为两边的数据已经保持一致了, 这是很危险的思维。
甚至可能导致数据丢失再也找不回来。
根据主从同步原理,可以理解为在备份二进制日志上的增量实时同步,或者从数据库删除了数据,或者在恢复时跳过了错误数据,导致主从并不一致,都是有可能的。
唯一保险的方法就是进行数据检查。
pt-table-checksum
也是mysql的工具之一,mysql真的几乎把所有情况都涉及到了,很成熟的数据库。
通过该工具可以实现主从之间的数据库一致性检验。
检验结果将会保存在一个新的表里面。然后通过pt-table-sync工具将该表的数据转化,来修复主从间的不一致。
使用pt-table-checksum的注意事项就是,主从数据库要配置一套同样的账号密码,才能通过pt-table-checksum进行检查。
pt-table-checksum --nocheck-replication-filters --recursion-method=hosts
--replicate=mc_test.checksums --databases=mc_test --tables=userinfo
h=127.0.0.1,u=root,p=MyPassword,P=3306
然后会在路径mc_test.checksums下自动创建checksums表,将异常数据写进去。
pt-table-sync
该工具可以将pt-table-checksum检查出来不一致的数据,进行修复。让主从数据保持一致。
使用pt-table-sync的注意事项:
1. 主从数据库要配置一套同样的账号密码,才能通过pt-table-sync进行恢复。
2. 该操作会锁表
命令
pt-table-sync --replicate=mc_test.checksums --no-check-child-tables --no-foreign-key-checks
--databases=mc_test --tables=userinfo h=127.0.0.1,u=root,p=MyPassword,P=3306 --execute
五、 主从切换
前面一切铺垫好后
现在要做的,就是将数据源切换为新数据库。
- 在新数据库上创建旧有数据库的账号密码,创建应用集群白名单访问权限,并进行连接测试。
- 修改各个应用程序的数据库IP访问地址
- 网站首页切换为网站维护通告
- 配置从库的binlog日志,重启生效。
- 开始切换操作
主从切换主要防止数据丢失。
首先停止master端写入
该命令锁住范围较大,根据自己业务情况使用。
FLUSH TABLES WITH READ LOCK
其次等待slave端IO和SQL线程都已完成等待最新状态同步状态。这一步很重要!
然后停止salve。
stop slave;
重置从数据库的master
reset master;
重置从数据库的slave
reset all slaves;
查看从数据库master当前binlog位置:
show master status;
授权新账号给主数据库
GRANT REPLICATION CLIENT,REPLICATION SLAVE ON *.* TO ‘master账号’@‘master的ip’ IDENTIFIED BY ‘master密码’;
主数据库进行操作,
连接从数据库
change master to master_host='10.248.33.118', master_user='master账号',
master_password='master密码', master_log_file='mysql-bin.000001',
master_log_pos=120;
开启slave同步
start slave;
查看主数据库同步状态:
show slave status \G
切换成功后,
此时原来的主数据库变成了新的从数据库。
原来的从数据库变成了新的主数据库。
六、解除
启动应用程序连接,解除网站维护通告。