MySQL for data migration


When we are faced with an unknown database business system and need to complete the migration of the entire business (application + database) within a certain period of time, preliminary environmental research, migration plan formulation, migration test drill, formal migration cutover, migration rollback plan , Every step is a top priority and indispensable. This document mainly sorts out some general concerns during the entire migration process, which can help you quickly get started with database migration.

1. Environmental research

No matter what database we migrate, the first step we need to do is to understand the basic environmental information of the database we want to migrate, its usage, and the flow of the entire business topology. In this way, we can try to avoid some detours during the first migration test.

1.1 Server information

Owned business system server nickname Server IP server configuration Storage configuration Database IP: port Database version
xxx_production xxx_prod 172.16.xx.xx 16C128G SSD 2T 172.16.xx.xx:3306 MySQL 5.7.33
xxx_ pre-release xxx_stg

1.2 Database information

1.2.1 Basic database information

If MySQL is migrated to a self-built environment, then we'd better use the my.cnf file of the source environment to initialize and apply the database, but if we need to migrate the self-built database to some cloud database environment, some key factors that affect the use of the database Parameters will affect the formulation of our migration plan and the normal business use of the target environment. We still need to focus on the following parameters:

Database version Transaction isolation level Automatic submission Server_id Whether to open binlog binlog mode binlog mirror mode Case Sensitive Index prefix upper limit sql_mode
5.7.20-log READ-COMMITTED 1 33061 1 ROW FULL 0 1 STRICT_TRANS_TABLES,NO_ZERO_IN_DATE

Related SQL support:

mysql> SELECT version(), @@transaction_isolation, @@autocommit, @@server_id, @@log_bin, @@binlog_format, @@binlog_row_image, @@lower_case_table_names, @@innodb_large_prefix, @@sql_mode;

1.2.2 Database user information

Database account Authority Business
monitor@% GRANT PROCESS, REPLICATION CLIENT ON . TO ‘monitor’@’%’ xxx_a
root@localhost GRANT ALL PRIVILEGES ON . TO ‘root’@‘localhost’ WITH GRANT OPTION xxx_b
sansi_rw @% GRANT ALL PRIVILEGES ON . TO ‘sansi_rw’@’%’ xxx_c

Related SQL support:

-- 查看当前数据库用户列表
mysql> select user,host from mysql.user;

-- 查看制定数据库用户权限
mysql> show grants for 'root'@'localhost';

1.3 Research on library table information

1.3.1 Overview of database object statistics

database Object type Number of objects
db1 EVENTS 1
db1 PROCEDURE 2
db1 TABLE 4
db1 TRIGGER 1
db1 VIEW 2

1.3.2 Overview of database information statistics

database character set Proofreading rules Estimated number of records Estimated data capacity (MB) Estimated index capacity (MB) Estimated free space (MB) Estimated total size (MB)
mysql utf8mb4 utf8mb4_general_ci 1982 2.11 0.15 4.00 6.31
BIGDATA_ORDER utf8mb4 utf8mb4_general_ci 2611 0.21 0.00 0.00 0.21
information_schema utf8 utf8_general_ci NULL 0.10 0.00 1230.00 1230.10
db1 utf8 utf8_general_ci 9 0.03 0.00 0.00 0.03
AAA_bbb utf8 utf8_general_ci 10 0.02 0.00 0.00 0.02
sys utf8 utf8_general_ci 6 0.01 0.00 0.00 0.01
db2 utf8 utf8_general_ci 4 0.01 0.00 0.00 0.01
performance_schema utf8 utf8_general_ci 1322296 0.00 0.00 0.00 0.00
db3 utf8 utf8_general_ci NULL NULL NULL NULL NULL

1.3.3 Table information statistics overview

Database name Table Name engine Line mode Is there a primary key Estimated data capacity (MB) Estimated index capacity (MB) Estimated free space (MB) Estimated total size (MB) Estimated number of rows
db1 t2 InnoDB Dynamic no 0.01 0.00 0.00 0.01 8
db1 AAA_bbb InnoDB Dynamic no 0.01 0.00 0.00 0.01 2
db1 t1 InnoDB Dynamic Have 0.18 0.00 0.00 0.18 2605
db1 child InnoDB Dynamic Have 0.01 0.00 0.00 0.01 0
db1 parent InnoDB Dynamic Have 0.01 0.00 0.00 0.01 0

1.3.4 Whether there is a duplicate name table after ignoring case sensitivity

data Library table name Statistics
xx xx 2

Related SQL support:

-- 数据库对象统计概览
select db AS '数据库',type AS '对象类型',cnt AS '对象数量' from
(select 'TABLE' type,table_schema db, COUNT(*) cnt  from information_schema.`TABLES` a where table_type='BASE TABLE' group by table_schema
union all
select 'EVENTS' type,event_schema db,count(*) cnt from information_schema.`EVENTS` b group by event_schema
union all
select 'TRIGGER' type,trigger_schema db,count(*) cnt from information_schema.`TRIGGERS` c group by trigger_schema
union all
select 'PROCEDURE' type,db ,count(*) cnt from mysql.proc d where`type` = 'PROCEDURE' group by db
union all
select 'FUNCTION' type,db,count(*) cnt  from mysql.proc e where`type` = 'FUNCTION' group by db
union all
select 'VIEW' type,TABLE_SCHEMA,count(*) cnt  from information_schema.VIEWS f group by table_schema  ) t
order by db,type;

-- 数据库信息统计概览
select a.SCHEMA_NAME AS '数据库名', a.DEFAULT_CHARACTER_SET_NAME AS '字符集', a.DEFAULT_COLLATION_NAME AS '校对规则', sum(table_rows) AS '记录数总计', sum(truncate(data_length/1024/1024, 2)) AS '预估数据容量(MB)', sum(truncate(index_length/1024/1024, 2)) AS '预估索引容量(MB)', sum(truncate(data_free/1024/1024, 2)) AS '预估空闲空间(MB)', sum(truncate((data_length+index_length+data_free)/1024/1024, 2)) AS '预估总大小(MB)'  from INFORMATION_SCHEMA.SCHEMATA a left outer join information_schema.tables b on a.SCHEMA_NAME=b.TABLE_SCHEMA group by a.SCHEMA_NAME,  a.DEFAULT_CHARACTER_SET_NAME,a.DEFAULT_COLLATION_NAME order by sum(data_length) desc, sum(index_length) desc;

-- 表信息统计概览
select a.table_schema AS '数据库名', a.table_name as '表名', a.ENGINE as '引擎', a.ROW_FORMAT as '行模式', case when tmp.table_name is null then '有' when tmp.table_name is not null then '无' end '是否有主键', truncate(data_length/1024/1024, 2) AS '预估数据容量(MB)', truncate(index_length/1024/1024, 2) AS '预估索引容量(MB)', truncate(data_free/1024/1024, 2) AS '预估空闲空间(MB)', truncate((data_length+index_length+data_free)/1024/1024, 2) AS '预估总大小(MB)', a.table_rows as '预估行数' from information_schema.tables  a left join ( select table_schema,table_name from information_schema.tables where (table_schema,table_name) not in(     select distinct table_schema,table_name from information_schema.columns where COLUMN_KEY='PRI' ) and TABLE_TYPE='BASE TABLE' and table_schema not in ('sys','mysql','information_schema','performance_schema') ) tmp on a.table_schema=tmp.table_schema and a.table_name=tmp.table_name where a.TABLE_TYPE='BASE TABLE' and a.table_schema not in ('sys','mysql','information_schema','performance_schema') order by a.table_schema,data_length desc;


-- 忽略大小写敏感后是否存在重名表
select table_schema as '数据库',lower(table_name) as '表名',count(*) as '统计数' from information_schema.tables group by table_schema,lower(table_name) having count(*) >1;

1.4 Data stream topology

数据流拓扑可帮助我们了解在整个业务模块中,该数据库的整个数据来源以及流向。首先就拿数据源来讲,可能数据库的数据源除应用程序1、应用程序2等等,此外可能还存在一些数据周期性的同步任务,这就需要我们在整个迁移乃至割接过程中需要协调各方人员一起配合完成整个迁移工作。其次是数据流向/使用也可能是多种多样的,我们需要调研清楚这些信息,方便我们规划在整个迁移中的数据/业务验证方式。

二、方案制定

2.1 各种方案特点对比

方案 优势 劣势 描述
依赖原生复制 可达到数据的实时同步,割接停机窗口耗时最短;可直接对原master进行复制,也可对slave进行级联复制,MySQL 5.7以上也可实现多源复制;可设置复制对象 master、级联复制源的slave需要开启binlog相关参数;若数据库中存在频繁对无主键表的DML,复制延迟将会很大;受限于数据库版本兼容性
xtrabackup 物理备份恢复速度相对较快,可通过全量备份+增量备份+binlog的方式缩短割接停机窗口 需要预留一定的割接停机窗口,物理恢复不可跨版本迁移;不可单独迁移其中某个数据库/表
mysqldump 适用于数据量相对较小,需要跨版本迁移的场景;可通过全量dump+binlog增量恢复的方式缩短割接停机窗口;迁移对象灵活 需要预留一定的割接停机窗口,逻辑恢复相对较慢,不适用于数据量较大的场景;
DTS 比较成熟的数据同步工具,可实现全量+实时增量同步,割接停机窗口耗时最短;比较适用于自建上云使用;迁移对象灵活 需要开启相关binlog才可进行增量同步;对无主键表进行了一定的优化,但还是不能很好支持无主键表的频繁变更操作增量同步;依赖阿里,部分报错处理只能通过阿里进行支持
Dataworks 一种离线数据处理工具,适用于数据库异构改造迁移;迁移对象灵活 必须源环境停止业务后,才可进行一次性迁移处理,割接停机窗口耗时最大;表级别配置迁移任务
canal 阿里开源项目,可通过binlog实现增量实时同步;迁移对象灵活 与DTS相同

2.2 数据库账号权限

源端数据库账号权限要求:

  • 物理备份用户权限:RELOAD, PROCESS, LOCK TABLES, REPLICATION CLIENT
  • 原生复制用户权限:REPLICATION SLAVE
  • DTS/canal:全量操作:待迁移数据库SELECT权限 ; 增量操作:待迁移数据库SELECT权限、REPLICATION SLAVE、REPLICATION CLIENT、SHOW VIEW

目标端数据库账号权限要求:迁移数据库的读写权限

2.3 迁移步骤/进度记录

迁移任务 迁移步骤 重要过程和问题 结果记录 预计执行时间 实际完成时间 执行人 配合方 是否通过 进度 描述
迁移任务1 目标环境数据库部署 - 已完成 2021-03-01 2021-03-01 xxx - 通过 已完成
- 源/目标网络打通 - 已完成 2021-03-03 2021-03-03 xxx yyy 通过 已完成
- 源/目标数据库账号申请 - 已完成 2021-03-03 2021-03-03 xxx yyy 通过 已完成
- 连通性测试 - 已完成 2021-03-03 2021-03-03 xxx - 通过 已完成
- 前置任务 需要业务方配置的一些业务关停等操作,根据实际编写 已完成 2021-03-05 2021-03-05 yyy xxx 通过 已完成
- 数据迁移 迁移对象记录、迁移时间记录、迁移中问题点记录 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
- 数据校验 常规count校验,业务校验 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
- 业务割接 - 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
- 回滚方案 - 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
迁移任务2

2.4 数据迁移中的一些关注点

  • 评估跨版本迁移的风险性和兼容性,跨版本下业务需要提前做好测试
  • 迁移源/目标中关键性参数尽量保证一致,特别是1.2.1 中提到的一些关键参数、以及数据库字符集格式等
  • 在使用一些利用binlog进行数据同步迁移方案中,要考虑目标端event、trigger对数据一致性的影响
  • 数据校验中,重要数据还是需要业务层进行业务校验

三、迁移演练

3.1 迁移演练记录

迁移任务 迁移步骤 重要过程和问题 结果记录 预计执行时间 实际完成时间 执行人 配合方 是否通过 进度 描述
迁移任务1 目标环境数据库部署 - 已完成 2021-03-01 2021-03-01 xxx - 通过 已完成
- 源/目标网络打通 - 已完成 2021-03-03 2021-03-03 xxx yyy 通过 已完成
- 源/目标数据库账号申请 - 已完成 2021-03-03 2021-03-03 xxx yyy 通过 已完成
- 连通性测试 - 已完成 2021-03-03 2021-03-03 xxx - 通过 已完成
- 前置任务 需要业务方配置的一些业务关停等操作,根据实际编写 已完成 2021-03-05 2021-03-05 yyy xxx 通过 已完成
- 数据迁移 迁移对象记录、迁移时间记录、迁移中问题点记录 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
- 数据校验 常规count校验,业务校验 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
- 业务割接 - 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
- 回滚方案 - 已完成 2021-03-05 2021-03-05 xxx yyy 通过 已完成
迁移任务2

3.2 迁移方案优化

迁移方案的演练,是为了踩一些我们未能预料到的坑,也是为了后续更好的评估整个方案的可行性,让我们对整个迁移方案做出更好的优化,迁移方案的优化主要关注:

  • 迁移中未考虑到的点
  • 迁移步骤可行性
  • 迁移时间窗口限制

四、迁移割接/业务验证/回滚

迁移割接采取怎样的方案很大程序上依赖我们迁移方案的选择。我们需要确认好以下几点:

  • 具体的割接执行步骤
  • 评估割接时间窗口
  • 数据/业务验证方式
  • 回滚方案

4.1 数据验证脚本

一般而言检查mysql数据一致性使用count计数进行校验。对于checksum,checksum默认会对表记录一行一行进行校验,且校验期间会对表加read lock,若数据库存在大表,请谨慎操作!!!!

#cat mysql_check.sh
#!/bin/sh
#****************************************************************#
# ScriptName: mysql_check.sh
# Author: Sansi
# Create Date: 2019-11-23 15:30
# Modify Author: Sansi
# Modify Date: 2019-12-17 11:19
# Function:
# Usage: bash mysql_check.sh db1 [db2] ... [dbN]
#***************************************************************#
#!/bin/bash

#source info
#source_user=transfer
s_user=${db_user}
s_host=172.16.x.xx
s_port=${db_port}
s_password=${db_password}

#target info
t_user=${db_user}
t_host=172.16.x.xx
t_port=${db_port}
t_password=${db_password}

#检查db下每张表的checksum值
Checksum(){
	t_checksum=`mysql -u${t_user} -p${t_password} -h${t_host} -P${t_port} -e "checksum table ${table_name};" | grep -v Checksum | awk '{print $2}'`
	s_checksum=`mysql -u${s_user} -p${s_password} -h${s_host} -P${s_port} -e "checksum table ${table_name};" | grep -v Checksum | awk '{print $2}'`

	if [ ${t_checksum} -eq ${s_checksum} ]
	then
		echo -e "${table_name} \tchecksum is ok"
	else
		echo -e "${table_name} \tchecksum is not ok"
	fi
}

#遍历需要校验的所有db,并检查每个db下每张表的count数
for db in $@
do
	echo -e "Begin check Schema : $db ..."
	#导出db下所有表的目录
	mysql -u${s_user} -p${s_password} -h${s_host} -P${s_port} -e "select concat(table_schema,\".\",table_name) from information_schema.tables where table_schema='$db';" | grep ${db}>${db}.txt

for table_name in `cat ${db}.txt`
do
		t_count=`mysql -u${t_user} -p${t_password} -h${t_host} -P${t_port} -e "select count(*) from ${table_name};" | grep -v count`
		s_count=`mysql -u${s_user} -p${s_password} -h${s_host} -P${s_port} -e "select count(*) from ${table_name};" | grep -v count`

		if [ ${t_count} -eq ${s_count} ]
		then
			echo -e "${table_name} \t's count is ok ..."
			#Checksum
		else
			echo -e "${table_name} \tcount is different\tScource:${s_count}\tTarget:${t_count}."
			
		fi

done
done

Guess you like

Origin blog.csdn.net/weixin_37692493/article/details/115110014