01 数据库服务主从同步(基础方式)
1)主从故障排查思路
查看主从状态
sql
show slave status\G
关键状态信息
sql
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
说明:从库上两个关键线程,状态为Yes,表示主从同步正常
sql
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
说明:查看错误提示信息
sql
Master_Log_File: binlog.000001
Read_Master_Log_Pos: 44565473
说明:表示主库dump线程发送的binlog日志文件和位置点信息
sql
Relay_Master_Log_File: binlog.000001
Exec_Master_Log_Pos: 44565473
说明:表示relay log日志中回放数据信息binlog文件和位置点
sql
SQL_Delay: 0
SQL_Remaining_Delay: NULL
说明:从库是否开启了延迟同步功能
IO线程故障排查
情况一:Slave_IO_Running: connecting
- 连接地址、端口、用户、密码信息不对可能会导致连接异常
- 防火墙安全策略阻止连接建立、网络通讯配置异常影响连接建立
- 到达数据库服务连接数到达上限,造成主从连接产生异常
情况二:Slave_IO_Running: no
-
原因 :IO线程在请求日志信息失败,有可能日志信息被无意清理了
解决步骤:- 在从库上需要停止主从,并清理从库相关主从配置
- 在主库上需要切割日志信息,生成新的日志
- 在主库上重新进行数据备份,并将备份信息迁移到从库
- 在从库上恢复数据信息,根据备份文件binlog信息和位置点信息,重新配置主从功能
PS:在使用GTID功能实现主从同步时,可以让从库自动识别主库的binlog位置点信息
-
原因:IO线程在请求日志信息失败,有可能主从配置的标识信息重复冲突了
- server_id标识冲突
- server_uuid标识冲突
SQL线程故障排查
情况:Slave_SQL_Running: no
-
原因:SQL线程无法加载relaylog文件,可能relaylog文件被清理删除
-
原因 :SQL线程可以加载relaylog文件,加载relaylog文件事务信息后,做执行时产生了异常问题
sqlselect * from performance_schema.replication_applier_status_by_worker\G
避免主从冲突方案
可以在从库上设置只读功能:
ini
# 配置文件设置
[mysqld]
read_only = 1
super_read_only = 1
注意:修改配置文件之后重启生效
产生主从冲突如何处理
方法01:将从库中冲突的数据信息删除
sql
-- 查询用于监控并行复制的工作线程状态
select * from performance_schema.replication_applier_status_by_worker\G
方法02:在从库上做忽略错误冲突错误
ini
# 配置文件设置
slave-skip-errors=1007
2)主从同步扩展知识
扩展主从同步方式01:基于GTID实现主从同步
优点:
- 解决了主从同步需要获取位置点的问题(无需人工去查找binlog点)
- 解决了主从同步位置点更新异常的问题
实现原理机制:在从库和主库之间实现主从同步,会利用GTID事务编号实现位置点自动识别
GTID实现主从同步步骤:
步骤一:准备主从实例主机
- 部署安装好数据库服务
步骤二:需要在主从主机配置GTID功能(两台机器都要配置)
ini
# 配置文件设置
gtid-mode=on
enforce-gtid-consistency=true
# 开启GTID功能
log-slave-updates=1
# 让从库也需要记录binlog日志功能
步骤三:在主库上进行数据备份/并在从库恢复数据
bash
# 主库备份
mysqldump -uroot -p1 -A --single-transaction --source-data >/backup/all.sql
# 传输备份文件到从库
scp /backup/all.sql root@10.0.0.203:/backup/
sql
-- 从库进入数据库恢复
source /backup/all.sql
知识补充 :
当主从数据库服务开启GTID功能后,进行主库数据备份时会有警告提示;建议利用--set-gtid-purged=OFF进行数据库备份
参数说明:
--set-gtid-purged=ON:只能将备份的数据信息用于主从同步--set-gtid-purged=OFF:可以将备份的数据信息用于修复数据
示例:
ini
--set-gtid-purged=ON
# 备份文件中会有以下信息显示
SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ 'c460ff8c-7f09-11f0-ba3a-000c291e91e6:1-3';
说明 :表示备份文件中,或者数据库服务中已经做过了什么事务操作
PS:一旦GTID功能开启,完成事务操作时,会具有幂等特性(做过的事情不会重复操作)
ini
--set-gtid-purged=OFF
# 备份文件中没有以下信息显示
SET @@GLOBAL.GTID_PURGED=/*!80000 '+'*/ 'c460ff8c-7f09-11f0-ba3a-000c291e91e6:1-3';
步骤四:在从库上做主从配置
sql
change master to
master_host='10.0.0.119',
master_user='repl',
master_password='1',
master_auto_position=1;
start slave;
注意 :之前如果配置过了,可以stop slave后,重置配置reset slave all;,再start slave
测试:
sql
-- 主库创建一个表测试
-- 然后查看从库状态
SHOW SLAVE STATUS\G
查看关键信息:
Retrieved_Gtid_Set:从主库获取到的GTID集合Executed_Gtid_Set:从库已经执行的GTID集合- 确保
Last_IO_Error和Last_SQL_Error为空
扩展主从同步方式02:实现主从延迟同步数据
1)主从延时同步原理
利用控制SQL线程,让SQL线程在指定时间后,进行relaylog文件事务信息的回放
dump → IO → relay日志 → SQL(意味着SQL会延迟读取relay文件中的事务信息)
2)主从延时同步实践
步骤一:准备主从实例主机
忽略...
步骤二:在主库上做好备份/从库进行数据恢复
省略...
步骤三:确认正常主从是否可以建立
sql
change master to
master_host='10.0.0.51',
master_user='repl',
master_password='123456',
master_auto_position=1;
start slave;
步骤四:需要停止主从SQL线程,进行延迟功能配置
sql
stop slave sql_thread;
change master to master_delay=300;
start slave sql_thread;
指标查看(成功):
sql
SQL_Delay: 300
SQL_Remaining_Delay: 289
3)如何利用延时从库修复数据
步骤一:主库模拟创建测试数据
sql
create table t1 (id int, name char(10));
insert into t1 values (1,'xiaoA'),(2,'xiaoB'),(3,'xiaoC');
步骤二:模拟管理数据库人员做了错误操作
sql
drop table t1;
步骤三:利用延时从库备份数据
sql
stop slave sql_thread; -- 或 stop slave;
示例:
sql
-- 在主库 (10.0.0.119) 查看binlog信息
SHOW MASTER STATUS;
SHOW BINLOG EVENTS IN 'binlog.000012'; -- 替换为实际的binlog文件
-- 找到相关操作的GTID,例如:
-- GTID: c460ff8c-7f09-11f0-ba3a-000c291e91e6:160 - CREATE TABLE
-- GTID: c460ff8c-7f09-11f0-ba3a-000c291e91e6:161 - INSERT
-- GTID: c460ff8c-7f09-11f0-ba3a-000c291e91e6:162 - DROP TABLE
-- 正确事务信息:
-- create table t1 (id int,name char(10)) GTID: 160
-- insert GTID: 161
-- 错误事务信息:
-- DROP TABLE `t1` GTID: 162
在从库中执行:
sql
start slave until sql_before_gtids="e51f74ac-8017-11f0-acab-000c2994e09d:6";
回到命令行备份数据:
bash
mysqldump -uroot -p1 xiaoA t1 --set-gtid-purged=OFF >/tmp/xiaoA_t1.sql
步骤四:在主库中恢复数据信息
bash
# 从库传输备份文件到主库
scp -rp /tmp/xiaoA_t1.sql 10.0.0.119:/backup/
sql
-- 主库恢复数据
mysql> source /backup/xiaoA_t1.sql
mysql> select * from t1;
+------+-------+
| id | name |
+------+-------+
| 1 | xiaoA |
| 2 | xiaoB |
| 3 | xiaoC |
+------+-------+
步骤五:恢复从库同步
sql
-- 在从库 (10.0.0.203) 执行
-- 重新设置延迟(如果需要继续保持延时从库)
CHANGE MASTER TO MASTER_DELAY = 300;
START SLAVE SQL_THREAD;
-- 检查同步状态
SHOW SLAVE STATUS\G
扩展主从同步方式03:半同步方式实现主从同步
1)数据库主从同步传输数据方式
异步方式:
client(事务处理请求) → master (完成事务操作) → binlog → dump →(事务信息传输,会有失败情况)→ IO → relaylog → SQL 回放
半同步方式(无损同步方式):
client(事务处理请求) → master (完成事务操作) → binlog → dump →(确认IO线程是否接收消息)→ IO → relaylog → SQL 回放
↓
ack确认
↑
dump ← IO(保存到了relaylog)→ SQL 回放
全同步方式:
client(事务处理请求) → master (完成事务操作) → binlog → dump →(确认IO线程是否接收消息)→ IO → relaylog → SQL 回放
↓(rollback) dump ←(10s超时)→ IO → relaylog → SQL 回放
2)数据库半同步复制实践过程
步骤一:准备主从实例主机
忽略...
步骤二:在主库上做好备份/从库进行数据恢复
省略...
步骤三:确认正常主从是否可以建立
sql
change master to
master_host='10.0.0.51',
master_user='repl',
master_password='123456',
master_auto_position=1;
sql
-- 先取消延时同步
stop slave sql_thread;
change master to master_delay=0;
start slave sql_thread;
sql
-- 从库检查是否异常
SHOW SLAVE STATUS\G
sql
-- 主库执行测试操作
USE xiaoA;
insert into t1 values (4,'xiaoD');
步骤四:修改异步方式为半同步复制
主库和从库中安装半同步复制功能插件
主库安装:
sql
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
-- 检查插件是否安装成功
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';
从库安装:
sql
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
-- 检查插件是否安装成功
SELECT PLUGIN_NAME, PLUGIN_STATUS
FROM INFORMATION_SCHEMA.PLUGINS
WHERE PLUGIN_NAME LIKE '%semi%';
激活主从数据库半同步复制功能:
启用半同步功能:
主库设置:
sql
set global rpl_semi_sync_master_enabled = 1;
# SET GLOBAL rpl_semi_sync_master_timeout = 1000; -- 超时时间1秒(默认)可以不用设置
从库设置:
sql
set global rpl_semi_sync_slave_enabled = 1;
重启从库IO线程:
sql
stop slave IO_THREAD;
start slave IO_THREAD;
3)验证半同步功能
1:主库检查半同步状态
sql
-- 查看半同步状态
SHOW STATUS LIKE 'Rpl_semi_sync%';
-- 重点关注:
-- Rpl_semi_sync_master_status: ON -- 主库半同步状态
-- Rpl_semi_sync_master_clients: 1 -- 连接的半同步从库数量
-- Rpl_semi_sync_master_yes_tx: 0 -- 通过半同步成功的事务数
-- Rpl_semi_sync_master_no_tx: 0 -- 降级为异步的事务数
2:测试半同步
sql
-- 在主库执行插入
INSERT INTO t1 VALUES (5, 'xiaoE');
-- 在主库检查状态
SHOW STATUS LIKE 'Rpl_semi_sync_master_yes_tx';
-- 这个值应该增加1,表示事务通过半同步成功提交
3:模拟从库故障,测试超时降级
sql
-- 在从库停止IO线程模拟故障
STOP SLAVE IO_THREAD;
-- 在主库执行插入(此时应该会超时后降级为异步)
INSERT INTO t1 VALUES (6, 'xiaoF');
-- 在主库检查状态
SHOW STATUS LIKE 'Rpl_semi_sync_master_no_tx';
-- 这个值应该增加1,表示事务降级为异步
-- 恢复从库
START SLAVE IO_THREAD;
4)永久化配置半同步
主库my.cnf文件中配置:
ini
[mysqld]
plugin-load = "rpl_semi_sync_master=semisync_master.so"
rpl_semi_sync_master_enabled = 1
rpl_semi_sync_master_timeout = 1000
从库my.cnf文件中配置:
ini
[mysqld]
plugin-load = "rpl_semi_sync_slave=semisync_slave.so"
rpl_semi_sync_slave_enabled = 1
重启服务:
bash
# 两个库都重启mysql生效
/etc/init.d/mysqld restart