关于tidb:技术分享-tidb-21升级到40操作文档

41次阅读

共计 16446 个字符,预计需要花费 42 分钟才能阅读完成。

作者:莫善

某互联网公司高级 DBA。

本文起源:原创投稿

* 爱可生开源社区出品,原创内容未经受权不得随便应用,转载请分割小编并注明起源。


一、前言

线上 tidb 集群都是 2.1.[5,7,8,17],因版本太低,面临诸多问题,比方治理难度大,热点问题,执行打算生效,性能瓶颈,其余已知 / 未知且无奈解决的问题,当初须要降级至 4.0.13 版本。在调研后发现,如果原地降级将须要屡次降级【2.1–> 3.0 –> 4.0】,放心原地降级遇到不可逆的故障,更放心的是解决不掉而影响业务,所以通过测试和评估,最终采纳数据迁徙的形式进行降级。

因为应用 2.1 版本的用户自身比拟少,更别提降级了,所以可参考的迁徙降级文档简直没有,在降级中遇到了很多问题,也踩了很多坑,本文整顿了降级操作流程,并标记每个步骤容易遇到什么问题及解决方案,权当经验交流,避坑指南。本文所有内容 / 操作命令仅供参考。

  • 因 5.0 基于 MySQL 8.0 协定,放心和业务不兼容,也因为 5.0+ 的小版本都还比拟小,放心稳定性,所以就不思考了,过后 4.0.13 是 4.0 最新的版本,就选了这个版本。
  • 曾经有 24 套 tidb 集群实现了从 2.1 到 4.0.13 的降级。

二、环境介绍

1、旧集群环境介绍

  • 已有的组件
角色 数量 端口
pd 3 5017
tidb 3 4000
tikv 3 20117
alertmanager 1 9093
prometheus 1 9100
grafana 1 3000
vip 192.168.1.100 4000
dns old.tdb.com 4000
  • 未列举的组件示意未启用该组件,因历史起因,集群并没有启用 pump 组件。
  • 端口布局也没什么法则
  • 预计减少的组件
角色 数量 端口
pump 3 23001
drainer 1 24001

2、旧集群访问信息

dns old.tdb.com
vip 192.168.1.100:4000 rs :
192.168.1.1:4000
192.168.1.2:4000
192.168.1.3:4000

3、新集群环境介绍

角色 数量 端口
pd 3 13002
tidb 3 15002
tikv 3 17002
ticdc 3 33002
alertmanager 1 21002
prometheus 1 19002
grafana 1 20002
vip 192.168.1.100 15002
dns new.tdb.com 15002
  • 端口采纳 2 + 3 的格局,前两位是组件编号,后三位示意集群编号。即后三位一样的示意同一个集群,前两位一样示意同一个组件。

4、新集群访问信息

dns new.tdb.com
vip 192.168.1.100:15002 rs :
192.168.1.1:15002
192.168.1.2:15002
192.168.1.3:15002

三、流程介绍

  • 1、dba 打印以后连贯 tidb 的 ip 列表让主业务方确认是否存在非本业务的 ip。确保所有应用该集群的业务都参加进来。
  • 2、dba 跟业务确认是否有重连机制。(开启 binlog 须要重启 tidb 组件)。
  • 3、dba 开启 binlog,这步须要滚动重启 tidb 组件,须要跟业务协商一个工夫窗口。
  • 4、dba 部署 4.0 环境并导入全量数据。
  • 5、dba 同步增量数据。
  • 6、dba 校验新旧集群数据一致性。
  • 7、dba 交付新环境,提供新的域名 + 端口。
  • 8、dba 提供只读账户,业务测试,验证业务场景(仅限读,不能写)。
  • 9、dba 同步权限。
  • 10、切换流量。

四、降级操作

1、打印旧集群拜访列表

ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb1 -P 4000 -ppassword
mysql> select distinct host from information_schema.processlist

ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb2 -P 4000 -ppassword
mysql> select distinct host from information_schema.processlist

ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb3 -P 4000 -ppassword
mysql> select distinct host from information_schema.processlist

登录所有 tidb 节点,每个节点的输入后果追加到一个文件,而后排序去重进行统计客户端 ip

2、确认是否有重连机制

3、开启 binlog 并全量备份

这步操作在 ansible 治理机执行

(1)编辑配置文件

ansible # vim /path/github/tidb-ansible-2.1.8/inventory.ini
  • 增加 pump 组件的监控

    [monitored_servers]
    monitor-pump1 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001
    monitor-pump2 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001
    monitor-pump3 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001
  • 增加 pump 组件
[pump_servers]
#上面三个是 pump 组件的机器, 如果启用 pump 组件还须要关上 enable_binlog = True
pump1 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001
pump2 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001
pump3 ansible_host=xxxx deploy_dir=/path/tidb-data/pump-23001
  • pump 端口设置及启用 binlog 参数
## Global variables
[all:vars]
pump_port = 23001

## binlog trigger
enable_binlog = True
#enable_binlog = False

如果不设置 enable_binlog = True,在部署 pump 的时候会被疏忽。另外须要留神,在 pump 能提供服务前,不能从新加载 tidb 的配置并重启,否则会导致业务写操作失败。

(2)编辑 pump 的配置

ansible # vim /path/github/tidb-ansible-2.1.8/conf/pump.yml
  • 批改 binlog 保留周期
global:
  # a integer value to control expiry date of the binlog data, indicates for how long (in days) the binlog data would be stored. 
  # must bigger than 0
  gc: 14

改成 14 天,防止全量数据导入工夫过长导致增量数据失落(binlog 被清理)。

(3)登录指标机器创立目录

登录各个 pump 节点创立目录及更改权限

ansible # ssh pump1
pump1   # mkdir -p /path/tidb-data/pump-23001
pump1   # chown -R tidb. /path/tidb-data/pump-23001

ansible # ssh pump2
pump2   # mkdir -p /path/tidb-data/pump-23001
pump2   # chown -R tidb. /path/tidb-data/pump-23001

ansible # ssh pump3
pump3   # mkdir -p /path/tidb-data/pump-23001
pump3   # chown -R tidb. /path/tidb-data/pump-23001

(4)在 ansible 治理机部署 pump 及监控

ansible # ansible-playbook deploy.yml -l monitor-pump1,monitor-pump2,monitor-pump3,pump1,pump2,pump3 -i inventory.ini

(5)在 ansible 治理机启动 pump 及监控

ansible # ansible-playbook start.yml -l monitor-pump1,monitor-pump2,monitor-pump3,pump1,pump2,pump3 -i inventory.ini

(6)登录 tidb 查看 pump 是否部署实现

ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P 4000 -ppassword
mysql> show pump status;
+------------+------------+--------+--------------------+---------------------+
| NodeID     | Address    | State  | Max_Commit_Ts      | Update_Time         |
+------------+------------+--------+--------------------+---------------------+
| xxxx:23001 | xxxx:23001 | online | 427138948355850245 | 2021-08-20 04:42:57 |
| xxxx:23001 | xxxx:23001 | online | 427138948395171844 | 2021-08-20 04:42:57 |
| xxxx:23001 | xxxx:23001 | online | 427138948408279045 | 2021-08-20 04:42:57 |
+------------+------------+--------+--------------------+---------------------+
3 rows in set (0.00 sec)

mysql> 

须要留神,<font color=’red’>2.1.6 之前的版本不反对这个查问操作,须要通过 binlogctl 进行查看 pump 的状态,如下示例。</font>

ansible #  /path/binlogctl -pd-urls=http://pd_host:pd_port -cmd pumps
INFO[0000] pump: {NodeID: xxxx:23001, Addr: xxxx:23001, State: online, MaxCommitTS: 432180280017551379, UpdateTime: 2021-08-20 04:45:57 +0800 CST} 
INFO[0000] pump: {NodeID: xxxx:23001, Addr: xxxx:23001, State: online, MaxCommitTS: 432180280004444167, UpdateTime: 2022-03-30 18:45:14 +0800 CST} 
INFO[0000] pump: {NodeID: xxxx:23001, Addr: xxxx:23001, State: online, MaxCommitTS: 432180280017551372, UpdateTime: 2022-03-30 18:45:14 +0800 CST} 

(7)在 ansible 治理机滚动重启 tidb 节点

<font color=’red’> 执行这个操作前,肯定要确保 pump 组件失常运行。</font>

ansible # ansible-playbook rolling_update.yml -t tidb -i inventory.ini

须要留神的是,这个操作可能会呈现 ansible 启动或者敞开动作失败(始终卡着直到超时),如果碰到这种状况,能够登录到指标机器手动进行启动或者进行。参考命令如下:

  • 启动 cd /path/tidb/scripts && sudo -u tidb bash start_tidb.sh
  • 进行 cd /path/tidb/scripts && sudo -u tidb bash stop_tidb.sh

(8)登录 tidb 查看 binlog 是否曾经开启

ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P 4000 -ppassword
mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | 1     |
+---------------+-------+
1 row in set (0.01 sec)
  • 须要留神,<font color=’red’>2.1.6 之前的版本 log_bin 恒等于 0</font>,就是说即使 enable_binlog = True,通过 show variables like ‘log_bin’; 查出来的也是 0,然而 pump 会记录 binlog。
  • 倡议挨个 tidb 都查看一遍。

(9)在 ansible 治理机更新监控

ansible # ansible-playbook rolling_update_monitor.yml -t prometheus -i inventory.ini

(10)创立全量备份

ansible # /path/mydumper -u user -p pass -h old.tdb.com -P 4000 -t 2 -F 32 --skip-tz-utc -o /backup_path/4000 -B db_name

备份须要留神:

  • 工具获取 https://docs.pingcap.com/zh/t…
  • 在业务低峰进行备份,否则可能会呈现网卡打满的状况(尤其是 tidb 是万兆网卡,tikv 是千兆网卡的架构)
  • 可能会因为 gc 工夫过短导致备份失败(通过调整 gc 工夫解决)
  • 可能因为 tidb 调配的内存过小导致备份失败(通过调整 tidb 内存解决)
  • 备份实现后倡议检查一下建表语句的文件,是否存在非法工夫格局 (“0000-00-00”),如果存在在导入新集群的时候会报错,须要跟业务沟通一下变更默认值。
  • mydumper 不反对限流备份,能够通过备份到磁盘性能很差的机器或者 cfs 这种网络存储,在肯定水平上实现了限流备份。

4、部署 4.0 环境并导入全量数据

乐观事务模型须要关注一下,<font color=’red’>4.0 尽管反对乐观事务模型,而且新建集群默认也是开启状态,然而要想一个操作用到乐观锁,还是有肯定的限定条件的,即非 autocommit 的事务。具体请参考这个文章的【6.2.3.2 局部】</font> https://book.tidb.io/session1…

(1)装置 tiup

ansible # curl --proto '=https' --tlsv1.2 -sSf https://tiup-mirrors.pingcap.com/install.sh | sh
ansible # . /root/.bash_profile
ansible # tiup --version
ansible # tiup update --self

(2)筹备拓扑文件

ansible # vim topology-oltp-xxx.yaml

global:
  user: "tidb"
  ssh_port: 22
  deploy_dir: "/tidb-deploy"
  data_dir: "/tidb-data"
  
monitored:
  node_exporter_port: 11000
  blackbox_exporter_port: 12000
  
pd_servers:
  - host: 10.0.1.4
  - host: 10.0.1.5
  - host: 10.0.1.6

tidb_servers:
  - host: 10.0.1.1
  - host: 10.0.1.2
  - host: 10.0.1.3

tikv_servers:
  - host: 10.0.1.7
  - host: 10.0.1.8
  - host: 10.0.1.9

cdc_servers:
  - host: 10.0.1.7
  - host: 10.0.1.8
  - host: 10.0.1.9

monitoring_servers:
  - host: 10.0.1.10

grafana_servers:
  - host: 10.0.1.10

alertmanager_servers:
  - host: 10.0.1.10

以上是官网提供的配置模板,请依据理论状况批改。

  • 倡议部署 ticdc(pump),防止须要回滚的时候可追溯增量数据。
  • 倡议每个组件独自一台机器。

(3)查看 tiup 治理机到各个节点的 ssh 通道是否失常

(4)部署集群

ansible # tiup cluster check tidb-oltp-xxx-v4.0.13 v4.0.13 topology-oltp-xxx.yaml
ansible # tiup cluster deploy tidb-oltp-xxx-v4.0.13 v4.0.13 topology-oltp-xxx.yaml
ansible # tiup cluster start tidb-oltp-xxx-v4.0.13
ansible # tiup cluster display tidb-oltp-xxx-v4.0.13
  • check 可能会报很多异样,能够依据提醒进行修复,很多异样也能够疏忽。请参考 https://docs.pingcap.com/zh/t…

(5)权限保护

ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -p
mysql> create user if not exists root@"192.168.1.%" IDENTIFIED BY 'password';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'192.168.1.%' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'pd1' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'pd2' WITH GRANT OPTION;
mysql> GRANT ALL PRIVILEGES ON *.* TO 'root'@'pd3' WITH GRANT OPTION;
  • 这里用空明码就能登录。
  • 这里须要加上 pd 节点的受权,而且要求是 root 用户 (还是给 all 权限吧,测试发现给 select 权限不行,没做更粗疏的权限测试),否则 dashboard 不能失常应用。
ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword
mysql> drop user if exists root@"%";

倡议删除 root@’%’ 这个空明码用户。

(6)导入全量数据

ansible # /path/loader -d /backup_path/4000 -h new.tdb.com -u user -p password -P 15002 -t 2 -status-addr ":9299"

复原须要留神:

  • 工具获取 https://docs.pingcap.com/zh/t…
  • 倡议在业务低峰进行复原
  • 可能会因为表情符导致 loader 失败,如果遇到,能够试试 Dumpling
  • 多个 loader 工作的场景,倡议避开默认端口,否则可能会因为端口抵触导致失败

5、同步增量数据

这步操作在 ansible 治理机执行

(1)在备份机获取备份点位(本例应用 ansible 治理机进行备份)

从备份目录查看 metadata 文件

ansible # cd /backup_path/xxx
ansible # cat metadata 

Started dump at: 2021-08-29 15:34:30
SHOW MASTER STATUS:
    Log: tidb-binlog
    Pos: 425971435565482001
    GTID:

Finished dump at: 2021-08-29 15:34:33
ansible # 

(2)批改配置文件

ansible # vim /path/github/tidb-ansible-2.1.8/inventory.ini
  • 增加 drainer 组件的监控
[monitored_servers]
monitor-drainer1 ansible_host=xxxx deploy_dir=/path/tidb-data/drainer-24001
  • 增加 drainer 组件
[drainer_servers]
drainer1 ansible_host=xxxx deploy_dir=/path/tidb-data/drainer-24001 initial_commit_ts="425971435565482001"
  • drainer 端口设置
## Global variables
[all:vars]
drainer_port = 24001

(3)筹备 drainer 的配置文件

ansible # vim /path/github/tidb-ansible-2.1.8/conf/drainer1_drainer.toml 

配置文件名命名规定为【别名_drainer.toml】,否则部署时无奈找到自定义配置文件。

# drainer Configuration.

# the interval time (in seconds) of detect pumps' status
detect-interval = 10

# syncer Configuration.
[syncer]

# disable sync these schema
ignore-schemas = "INFORMATION_SCHEMA,PERFORMANCE_SCHEMA,mysql"

# number of binlog events in a transaction batch
txn-batch = 2000

# work count to execute binlogs
worker-count = 32

disable-dispatch = false

# safe mode will split update to delete and insert
safe-mode = false

# downstream storage, equal to --dest-db-type
# valid values are "mysql", "pb", "tidb", "flash", "kafka"
db-type = "tidb"

# the downstream MySQL protocol database
[syncer.to]
host = "new.tdb.com"
user = "user"
password = "xxxx"
port = 15002

txn-batch 和 worker-count 的配置在配置文件默认值应该是 1,倡议依据理论状况改大点,如果太小可能呈现增量数据始终追不上的状况。

(4)部署 drainer 及监控

ansible # ansible-playbook deploy_drainer.yml -i inventory.ini -l drainer1
ansible # ansible-playbook deploy.yml -i inventory.ini -l monitor-drainer1

(5)登录新集群的 tidb,给 drainer 节点受权

ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword
mysql> create user if not exists user@"drainer_host" IDENTIFIED BY 'xxxx';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'user'@'drainer_host';

留神:新集群(4.0)要给 drainer 所在的主机受权,否则启动 drainer 将报错,为了演示不便,这里间接给了所有权限

(6)启动 drainer 及监控

启动 drainer 前倡议先确定一下指标库是否曾经存在 tidb_binlog 库,如果存在,且又须要从备份的点位开始增量同步,这种状况须要手动删除一下,要不然 drainer 会从 checkpoint 开始同步数据。(个别呈现在导入全量失败后须要从新导入全量,而后遗记清理 tidb_binlog 库)

ansible # ansible-playbook start_drainer.yml -i inventory.ini -l drainer1
ansible # ansible-playbook start.yml -i inventory.ini -l monitor-drainer1

(7)登录 tidb 查看 drainer 状态

ansible # /opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P 4000 -ppassword
mysql> show drainer status;
+------------+------------+--------+--------------------+---------------------+
| NodeID     | Address    | State  | Max_Commit_Ts      | Update_Time         |
+------------+------------+--------+--------------------+---------------------+
| xxxx:24001 | xxxx:24001 | online | 431972431138127904 | 2021-08-25 16:42:57 |
+------------+------------+--------+--------------------+---------------------+
1 rows in set (0.00 sec)

mysql> 

须要留神,<font color=’red’>2.1.6 之前的版本不反对这个查问操作,须要通过 binlogctl 进行查看 drainer 的状态,如下示例。</font>

ansible #  /path/binlogctl -pd-urls=http://pd_host:pd_port -cmd drainers
INFO[0000] drainer: {NodeID: xxxx:24001, Addr: xxxx:24001, State: online, MaxCommitTS: 432180589478543384, UpdateTime: 2021-08-25 16:45:57 +0800 CST} 

(8)更新监控

ansible # ansible-playbook rolling_update_monitor.yml -t prometheus -i inventory.ini

(9)登录 grafana 进行查看同步进度

留神:如果同步落后比拟大,能够在 alertmanager 将 drainer 的告警先禁用

6、校验新旧集群数据一致性

(1)下载工具

ansible # git clone https://gitee.com/mo-shan/check_data_for_mysql.git
ansible # cd check_data_for_mysql

(2)批改配置

  • 编辑配置文件
ansible # cd /path/check_data_for_mysql
ansible # vim conf/check.conf

mysql_user="xxxx"
mysql_passwd="xxxx"
mysql_port1="6666"
mysql_port2="6666"
mysql_host1="192.168.1.1"
mysql_host2="192.168.1.2"
max_count=10000
threads=5
max_threads_running=30
mysql_path="/opt/soft/mysql57/bin/mysql"
log_partition="/dev/sda3"
log_par_size="10"
skip_check_table=""skip_check_db="INFORMATION_SCHEMA,METRICS_SCHEMA,PERFORMANCE_SCHEMA,mysql,sys,tidb_binlog,test,tidb_loader,dm_meta" #不倡议改

请结合实际状况依据正文提醒进行相干配置

  • 批改工作门路
ansible # sed -i 's#^work_dir=.*#work_dir=\"/check_data_for_mysql_path\"#g' start.sh #将这里的 check_data_for_mysql_path 改成 check_data_for_mysql 的家目录的绝对路径 

(3)测试用例

  • 每次执行校验工作的时候 <font color=’red’> 强制要清空 log 目录,所以请做好校验后果的备份 </font>
  • 执行校验工作的时候 <font color=’red’> 强烈建议开启 screen</font>
  • 有网卡监控需要,<font color=’red’> 执行监控脚本时也强烈建议独自开启 screen 进行监控 </font>

第一步:先开启一个 screen 监控网络

ansible # screen -S check_net_4000
ansible # bash manager.sh -a start
[2022-01-18 11:55:34] [1000 Mb/s] [RX : 2    MB/S]  [TX : 2    MB/S]
[2022-01-18 11:55:35] [1000 Mb/s] [RX : 2    MB/S]  [TX : 4    MB/S]
[2022-01-18 11:55:36] [1000 Mb/s] [RX : 2    MB/S]  [TX : 2    MB/S]
[2022-01-18 11:55:37] [1000 Mb/s] [RX : 2    MB/S]  [TX : 3    MB/S]
[2022-01-18 11:55:38] [1000 Mb/s] [RX : 1    MB/S]  [TX : 2    MB/S]
[2022-01-18 11:55:39] [1000 Mb/s] [RX : 1    MB/S]  [TX : 2    MB/S]
[2022-01-18 11:55:41] [1000 Mb/s] [RX : 1    MB/S]  [TX : 2    MB/S]
[2022-01-18 11:55:42] [1000 Mb/s] [RX : 2    MB/S]  [TX : 8    MB/S]

第二步:新开启一个 screen 执行校验工作

ansible # screen -S check_data_4000
ansible # bash start.sh -d dba -t dbatest1 -f true 
[2022-01-17 20:32:19] [胜利] [192.168.1.1] [start.sh/start.sh] [f_prepare:130] [本次数据一致性查看开始]
[2022-01-17 20:32:19] [正告] [192.168.1.1] [start.sh/start.sh] [f_main:185] [本次数据一致性查看将查看如下库 : [dba] ]
[2022-01-17 20:32:19] [胜利] [192.168.1.1] [start.sh/start.sh] [f_main:203] [正在查看 dba 库]

[2022-01-17 20:32:19] [胜利] [192.168.1.1] [func/f_check_diff_for_mysql.sh] [f_check_diff_for_mysql:249] [dba.dbatest1] [表构造统一]

[2022-01-17 20:32:19] [胜利] [192.168.1.1] [func/f_check_diff_for_mysql.sh] [f_check_diff_for_mysql:491] [dba.dbatest1] [1,1] [00 d 00 h 00 m 00 s] [9.09%, (0:0)/1 ] [数据统一]
[2022-01-17 20:32:19] [胜利] [192.168.1.1] [func/f_check_diff_for_mysql.sh] [f_check_diff_for_mysql:491] [dba.dbatest1] [2,11] [00 d 00 h 00 m 00 s] [100.00%, (0:0)/1 ] [数据统一]
[2022-01-17 20:32:19] [胜利] [192.168.1.1] [func/f_check_diff_for_mysql.sh] [f_check_diff_for_mysql:504] [dba.dbatest1] [查看结束]

[2022-01-17 20:32:19] [胜利] [192.168.1.1] [start.sh/start.sh] [f_main:242] [本次数据一致性查看实现] [通过]

ansible # 

查看完结后会提醒查看通过,否则就是查看不通过。

  • 工具实现逻辑请参考 https://mp.weixin.qq.com/s/PP…

7、交付新环境

dba 提供新的域名和端口给业务,这里给业务提供一个只读账户即可。

ansible # /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword
mysql> create user if not exists read_only@"host" IDENTIFIED BY 'xxxx';
mysql> GRANT SELECT ON *.* TO 'read_only'@'host';

须要留神的是,交付新环境前先不要同步权限表(mysql.user)。

8、业务验证

请业务充沛验证。

9、同步权限表

tidb2.1 和 4.0 的权限表构造不统一,所以没法通过导出导入的形式同步权限,另外通过测试应用 pt 工具也是不行的,上面提供一个同步权限的脚本,2.1 到 4.0 版本测试无效,其余版本尚未测试。

#!/bin/bash
port=4000
mysql_comm="/opt/soft/mysql57/bin/mysql -u root -h old.tdb.com -P ${port} -ppassword"

for user in $(${mysql_comm} -NBe "select concat(user,'@','\"',host,'\"',':::',password) from mysql.user;" 2>/dev/null)
do
    user_tmp="$(awk -F:::'{print $1}'<<<"${user}")"
    pass_tmp="$(awk -F:::'{print $2}'<<<"${user}")"
    create_user="create user if not exists ${user_tmp} IDENTIFIED BY PASSWORD'${pass_tmp}';"
    drop_user="drop user if exists ${user_tmp};"
    grep -q "^root@" <<< "${user_tmp}" && {grant_user="$(${mysql_comm} -NBe"show grants for ${user_tmp}"2>/dev/null|sed's/$/ WITH GRANT OPTION;/g')"
        } || {grant_user="$(${mysql_comm} -NBe"show grants for ${user_tmp}"2>/dev/null|sed's/$/;/g')"
            echo "${drop_user}"
        }
    echo "${create_user}"
    echo "${grant_user}"
done

该脚本会将旧集群的权限打进去,确认无误后能够写到新集群。

ansible # bash show_grant.sh | /opt/soft/mysql57/bin/mysql -u root -h new.tdb.com -P 15002 -ppassword
  • 权限同步当前,<font color=’red’> 请业务不要做受权操作 </font>,如需受权新主机或新建用户,找 dba 帮助。
  • 非必要 <font color=’red’> 也请业务不要再做 ddl 操作 </font>,如有需要也请 dba 帮助。

10、切换流量

  • 业务切流量前,倡议将新集群的 tidb 挨个重启一遍,开释掉 auto_increment 缓存,重启结束后须要查看 drainer 工作的状态及提早,等没提早再联系业务进行切换。
  • 如果不重启,切到新集群后 <font color=’red’> 自增列主键可能会报大量【Duplicate entry ” for key ‘PRIMARY’】。</font>

这个流程其实很简略,间接将新集群的 tidb 主机替换到 vip 原来 rs 列表即可,或者新申请一个 vip,将原来的域名解析到新 vip。但因历史问题,原来的域名和 tidb 端口都不合乎治理标准,所以须要业务通过新的域名 / 端口拜访 tidb。

须要留神:将域名解析到新的 vip,这种仅对新进来的连贯起作用。

鉴于环境的特殊性,dba 提供了两种计划实现让业务通过新的域名端口拜访 tidb。

不论采纳哪种计划,在切流量当前都不倡议马上下掉旧域名。举荐的做法是删除旧域名对应的 vip 的 rs 列表,将新集群的 tidb 节点挂到旧域名对应的 vip 的 rs 列表(须要留神新 tidb 端口跟旧 vip 端口可能不统一),这样做是防止了业务漏切的状况,察看几天 dns 日志,确认没业务应用旧域名后再下掉。

(1)横蛮计划

业务间接批改连贯信息,应用 new.tdb.com:15002 来连贯 tidb。

因可能存在多个业务应用该库,而且每个服务可能有多台业务机器,做不到所有服务同一时刻都切到新库,所以会呈现上面几种状况:

1)写新库,读旧库会读不到,因为新库跟旧库没有同步链路。

2)写旧库,读新库,可能会读不到,因为旧库跟新库之间存在提早。

防止不了双写,可能会导致上面的问题。

  • A. 更新同一行数据的两个连贯执行的工夫极短(小于旧库到新库的同步提早)。两个连贯是别离在旧库 / 新库执行,这时候该行数据的最终状态不是以谁最初执行为准。比如说,先在旧库执行了【update t set name = 1 where id = 2;】,而后在新库执行【update t set name = 2 where id = 2;】,实践上这个数据的记录最终应该是 name=2,然而思考到新库到旧库的同步有提早,这个数据就可能会被旧库的数据笼罩变成 name=1。如果反过来,先写新库,再写旧库,这种状况对数据没影响。
  • B. 业务的两个连贯在新库旧库别离插入同一行数据(主键一样或者惟一键一样的数据),如果先写新库,再写旧库,这样在业务端都会提交胜利,然而会导致旧库到新库的同步失败,因为旧库写入的数据同步到新库就会报主键抵触(惟一键抵触),这时候就须要 dba 人工干预进行修复。如果反过来,先写旧库再写新库(不思考旧库到新库的提早),这时候写新库的会话就会报错,这种状况对数据没影响。

针对上述的状况,<font color=’red’> 须要业务充沛评估。如果不能承受,能够倡议业务应用上面的平滑计划,这样影响面较小。</font>

(2)平滑计划

业务持续应用 old.tdb.com:4000 这个来连贯 tidb。

dba 须要将新集群的 tidb 加到旧集群的 vip 的 rs 列表,然而为了防止同时往新旧集群写数据,所以应该先将 vip 的 rs 先下掉,而后再将新集群的 tidb ip 加到 vip rs 列表。

这里波及两个动作:

  • 将旧集群的 vip 的 rs 列表清空(下线 rs),这里倡议被动开释连贯(重启 / 敞开旧集群的 tidb),要不然可能会呈现下掉 rs 后(具体须要看 vip 的实现机制),连贯不会开释。
  • 将新集群的 tidb 的 ip 加到旧集群 vip 的 rs 列表。

这两个操作须要跟业务确认好,因为下掉 rs 再重新加入有个时间差(预计 30s 之内),<font color=’red’> 这过程集群不可用。</font>

实现上述操作后,旧集群的访问信息会变成如下表:

dns old.tdb.com
vip 192.168.1.100:4000 rs :
192.168.1.1:15002
192.168.1.2:15002
192.168.1.3:15002

这时候业务须要挨个更新业务代码的配置,将旧域名和端口替换成新域名和端口(须要将 old.tdb.com:4000 替换成 new.tdb.com:15002),这时候再批改配置重启业务影响面会比拟小。

五、写在最初

本文档仅做教训分享,避坑指南,因应用场景各异,各自环境也不同,在迁徙过程中还可能碰上其余问题。<font color=’red’> 如有线上环境操作需要,请在测试环境充沛测试。</font>

正文完
 0