华为云-mysql实时同步
实时迁移是在用户只需要配置迁移的源、目标数据库及迁移对象即可完成整个数据迁移过程,再通过多项指标和数据的对比分析,帮助确定合适的业务割接时机,实现最小化业务中断的数据库迁移。
实时同步不同于实时迁移,实时迁移是以整体数据库搬迁为目的,而实时同步是维持不同业务之间的数据持续性流动。
[TOC]
风险提示
注意事项
- 在任务未结束前,不能修改源库和目标库的所有用户名、密码和用户权限等;
- 任何时候都不建议在目标库做ddl、dml,否则会导致数据不一致和任务失败;
- 全量迁移阶段,不建议对源实例做删除类型的DDL操作,比如删除数据库、索引、视图、字段等,增量阶段可以在源库做DDL;
- 增量迁移中,会过滤创建用户、删除用户及修改用户权限的DDL操作;
注:只会迁任务配置时候选中的可迁移的账号,而增量迁移阶段对源实例账号的修改不会被同步;
注:2021-11-19 增量迁移中,在目的端创建新账号、grant新账号to迁移任务中的db,不会影响drs同步任务;
- 迁移过程中,不允许源库写入binlog格式为statement的数据;
- 迁移过程中,不允许源库执行清除binlog的操作(比如purge),并非源库不能做mysqldump或者日志备份;
- 建议 expire_log_day > 7,确保恢复时断点处的binlog尚未过期,以保证服务中断后的顺利恢复;
- 在结束迁移任务时,才会迁移事件(EVENT)和触发器(TRIGGER),所以在任务结束之前,不要断开源库和目标库的网络连接;
- 源库不支持阿里云RDS的只读副本;
- 不支持非MyISAM和非InnoDB表的迁移;
- 如果源数据库为自建库,并且安装了Percona Server for MySQL 5.6.x或5.7.x时,内存管理器必须使用Jemalloc库,以避免Out of Memory问题;
遇到的坑
- 2021-10-18.全量迁移期间,由于开发同事对源表添加字段导致迁移中止,后来在目标表上手动添加该字段再续传就ok了。
- 2021-11-19.由于华为云RDS提供的root账号其实没有super权限,所以会导致source导入.sql备份文件的时候,function/view/procedure/trigger/event因导入失败而缺失,需要将备份文件中的 DEFINER='root'@'%' 去掉之后再导入。
参考:https://support.huaweicloud.com/rds_faq/rds_faq_0075.html
- 2021-11-24.由于阿里云金融区RDS不可配备公网ip而使用nginx转发,虽然阿里云ecs的安全组已允许同步实例访问10010端口 + 华为云rds的安全组已允许同步实例访问3306端口,但页面测试连接一直报错“DRS.KE0004:数据库不可用”。经验证,telnet 10010是通的,但mysql -P10010登录超时。后来设置阿里云rds的安全组允许ecs内网ip(172.16.24.80)访问就ok了。
阿里云-源库准备
1、准备测试数据
CREATE DATABASE db1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'user_db1'@'%' IDENTIFIED BY 'wSgjBrY5lqe!mbIu';
GRANT SELECT,INSERT,UPDATE ON db1.* TO 'user_db1'@'%';
FLUSH PRIVILEGES;
CREATE TABLE db1.t1(id bigint(20) unsigned auto_increment,create_time timestamp(3) default current_timestamp(3),primary key pk_t1(id));
CREATE TABLE db1.t2(id bigint(20), name varchar(10));
INSERT INTO db1.t1 VALUES();
INSERT INTO db1.t2(id) VALUES(1);
USE db1;
DROP PROCEDURE IF EXISTS proc_test;
DELIMITER //
CREATE PROCEDURE proc_test()
BEGIN
INSERT INTO t1 VALUES();
END
//
DELIMITER ;
CREATE EVENT IF NOT EXISTS event_test ON SCHEDULE EVERY 1 MINUTE STARTS '2021-08-24 00:00:00' ENDS '2022-01-01 00:00:00' DO CALL proc_test;
CREATE VIEW view_test AS (SELECT * FROM t1);
2、创建DRS迁移专用账号
若源数据库为阿里云数据库,则帐户需要同时具有mysql.user和mysql.user_view的SELECT权限
CREATE USER 'dba_drs_source'@'%' IDENTIFIED BY 'jPlr23_QY1whWac4';
GRANT SELECT,SHOW VIEW,EVENT,LOCK TABLES,REPLICATION SLAVE,REPLICATION CLIENT,TRIGGER ON *.* TO 'dba_drs_source'@'%';
GRANT SELECT ON mysql.user TO 'dba_drs_source'@'%';
GRANT SELECT ON mysql.user_view TO 'dba_drs_source'@'%';
FLUSH PRIVILEGES;
3、源库绑定公网ip
由于阿里云和华为云的内网没有打通,且阿里云RDS无法配置公网ip,只能在阿里云的一台ECS上配置了nginx代理,信息如下:
ecs内网ip:172.16.24.80
ecs公网ip:116.62.249.231
nginx端口:10008
nginx配置如下:
cat /var/app/nginx/conf.d/bigData.conf
server {
listen 10008;
proxy_timeout 300s;
proxy_pass rm-xx123456.mysql.rds.aliyuncs.com:3306;
}
4、确认核心参数
请确认如下14个核心参数是否配置正确,否则会导致迁移失败。
Variable_name | Value | 备注 |
---|---|---|
binlog_format | ROW | 【强制】binlog日志格式必须为ROW格式 |
binlog_row_image | FULL | 【强制】binlog_row_image需设置为FULL |
collation_server | xxx | 【强制】源和目标的collation_server需保持一致 |
expire_logs_days | 14 | 【建议】binlog保存时间越长越好,默认为0不清理,建议>3天 |
gtid_mode | ON | 【建议】GTID建议为开启状态 |
innodb_strict_mode | xxx | 【强制】源和目标的innodb_strict_mode需保持一致 |
log_bin | ON | 【强制】binlog日志必须打开 |
log_slave_updates | ON | 【建议】log_slave_updates设置为开启状态 |
lower_case_table_names | 0 | 【强制】源和目标的值需保持一致,且MySQL 8.0不支持该值=0的迁移 |
server_id | 1013406 | 【强制】增量迁移必须设置源数据库的server-id |
skip_name_resolve | ON | 【建议】开启 skip-name-resolve 减少连接超时的可能性 |
sql_mode | xxx | 【强制】源和目标的sql_mode需保持一致 |
time_zone | xxx | 【强制】源和目标的time_zone需保持一致 |
tx_isolation | xxx | 【强制】源和目标的tx_isolation需保持一致 |
确认
show variables where variable_name in ('log_bin','binlog_format','server_id','expire_logs_days','skip_name_resolve','gtid_mode','log_slave_updates','binlog_row_image','lower_case_table_names','collation_server','time_zone','sql_mode','innodb_strict_mode','tx_isolation');
源数据库的其他要求
- 源数据库和目标数据库的字符集需保持一致,否则迁移失败;
- 通常,阿里云RDS默认隔离级别: READ-COMMITTED,而华为云RDS默认隔离级别:REPEATABLE-READ(改华为云吧,不需要重启即可生效);
5、源库无主键表检查
- 确认源库是否存在无主键的表,由于无主键表的性能低于主键表的性能,建议为无主键表添加主键;
- 关于无主键表,DRS的迁移对比服务,只支持行数对比,不支持内容对比;
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_type = 'BASE TABLE' AND table_name NOT IN (SELECT DISTINCT table_name FROM information_schema.columns WHERE column_key = "PRI")
AND table_schema NOT IN ('mysql', 'information_schema', 'sys', 'performance_schema');
确认是否存在事件、存储过程、触发器。
SELECT db,name FROM mysql.event; SELECT db,name,type FROM mysql.proc WHERE db NOT IN('mysql', 'information_schema', 'sys', 'performance_schema'); SELECT TRIGGER_SCHEMA,TRIGGER_NAME FROM information_schema.triggers WHERE TRIGGER_SCHEMA NOT IN('mysql', 'information_schema', 'sys', 'performance_schema');
若有event,请确认是否开启事件定时器:
show variables like '%event_scheduler%';
华为云-目标库准备
1、目标实例限制
- 【强制】目标实例必须有足够的磁盘空间
- 【强制】目标实例不能包含与源实例同名的数据库,系统数据库除外
2、创建DRS迁移专用账号
CREATE USER 'dba_drs_dest'@'%' IDENTIFIED BY 'jPlr23_QY1whWac4';
GRANT SELECT,CREATE,ALTER,DROP,DELETE,INSERT,UPDATE,INDEX,EVENT,CREATE VIEW,CREATE ROUTINE,TRIGGER ON *.* TO 'dba_drs_dest'@'%' WITH GRANT OPTION;
GRANT SELECT,INSERT,UPDATE,DELETE ON mysql.* TO 'dba_drs_dest'@'%';
FLUSH PRIVILEGES;
- 若要迁移用户,请确保目标库账号授予不低于待迁移账号的权限,而源库只需要有mysql.user的SELECT权限即可;
- 建议目标库使用root账号;
3、确认核心参数
除了源数据库的几个核心参数外,再确认如下3个核心参数是否配置正确,否则会导致迁移失败。
Variable_name | Value | 备注 |
---|---|---|
log_bin_trust_function_creators | ON | 【强制】目标库的log_bin_trust_function_creators需设置为on |
max_allowed_packet | 536870912 | 【建议】目标库max_allowed_packet大于100MB,比如 512MB |
version | xxx | 【强制】不支持从高版本迁移到低版本 |
确认
show variables where variable_name in ('version','max_allowed_packet','log_bin_trust_function_creators');
目标数据库的其他要求
- 【强制】所选迁移对象和外键依赖的表需一起进行迁移,否则会导致迁移失败
- 【强制】迁移的对象中包含引擎为MyISAM的表,则目标数据库sql_mode不能包含no_engine_substitution参数,否则可能会导致迁移失败
迁移过程
1、创建迁移任务-入云
- 入云,指目标端数据库为华为云RDS;
- 迁移任务会创建一个临时的迁移实例,并配备一个弹性公网IP,比如:119.3.158.87,请在源实例的白名单中加入该IP,确保源库与此IP可连通。
2、将弹性公网ip加入源实例白名单
由于源实例使用的是 ecs + nginx 代理,所以需要调整ECS所属安全组的入方向规则,允许迁移实例的弹性公网ip访问:
优先级 | 协议端口 | 授权对象 | 描述 |
---|---|---|---|
66 | TCP : 10008 | 119.3.158.87 | 2021.08.20.dba测试华为DRS而临时开放.1周后可删 |
3、配置源库及目标库信息
- 目标库信息:所有Definer迁移到该用户下,记得选“否”,否则迁移后,所有源数据库对象的Definer都会迁移至该临时用户(dba_drs_dest日后是要删除的)下;
- 补充:还是建议使用root账号,并将所有Definer迁移到该用户下,选“是”。
4、迁移用户及对象
- 若要迁移用户,请确保目标库账号(还是使用root账号吧)授予不低于待迁移账号的权限,而源库只需要有mysql.user的SELECT权限即可;
- 考虑到我司专线带宽仅20Mbps,建议限速 2MBps
5、预检查
- 结合这一步“Definer迁移用户检查”的提示,建议在上面配置目标库的时候,使用root账号,并将所有Definer迁移到该用户下;
6、参数对比
- 这里,提供了一键对齐的按钮,将对比结果不一致的参数,修改目标库与源库一致,如下图示:
下一步,提交任务。
7、源库测试及目标库验证
源库:执行如下ddl及dml操作,并在目标库上确认数据是否已同步。
ALTER TABLE db1.t2 ADD COLUMN update_time timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) AFTER id; CREATE TABLE db1.t3(id int,create_time timestamp(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3)); INSERT INTO db1.t3(id) VALUES(1);
目标库:确认已同步了事件、存储过程、触发器;
SELECT db,name FROM mysql.event; SELECT db,name,type FROM mysql.proc WHERE db NOT IN('mysql', 'information_schema', 'sys', 'performance_schema'); SELECT TRIGGER_SCHEMA,TRIGGER_NAME FROM information_schema.triggers WHERE TRIGGER_SCHEMA NOT IN('mysql', 'information_schema', 'sys', 'performance_schema');
若有event,请确认是否开启事件定时器:
show variables like '%event_scheduler%';
9、最后的业务割接
持续同步中:
- 在任务未结束前,不能修改源库和目标库的所有用户名、密码和用户权限等。
- 迁移进度:确保全量迁移进度为100%,增量时延为1s以内,稳定保持一段时间。
- 迁移对比:对源库和目标库的对象级对比、数据级对比、用户对比,确保对比结果均为“一致”状态。
结束迁移步骤:
- 1、在割接阶段,先停掉源业务写入几分钟;
- 2、迁移对比:对源库和目标库的数据级对比,确保对比结果均为“一致”状态;
注:若在迁移任务运行中,关闭或断开了源库连接,则会导致触发器或事件未迁移,所以在任务结束之前不要禁用源库账号或关闭源实例mysql服务;
- 3、在实时迁移管理页面,单击对应任务的“结束”按钮,DRS将断开源数据库和目标数据库之间的连接,并恢复目标数据库读写;
注:结束任务之前,目标库处于read-only模式(目标实例其他库不受影响),即便root用户也无法写入,很棒。
- 4、若整个实例迁移的话,建议停止源实例mysql服务,以避免非常用业务访问到源库;
- 5、切换数据库:通知运维同事修改应用系统配置,并测试切换后的业务系统;