今天发生了与之前某篇博客相似的问题,有同学在不同步的 binlog 库中使用语句 database.table 命令对表进行 drop 导致 master 丢弃该表但是从库并未能同步到该操作。并且后续又实用 use xxxx 对该表进行增删字段,由于salve 并未建立此表于是 slave 崩溃的情况。

slave 崩溃信息通过查看 MySQL 错误日志差不多是这样

2019-07-11 15:05:12 17674 [ERROR] Slave SQL: Error 'Table'api.ring_king_record'doesn't exist'on query. Default database:'api'. Query:'ALTER TABLE `api`.`ring_king_record`

CHANGE COLUMN `course_id` `course_id` VARCHAR(45) NULL DEFAULT ''AFTER `id`,

CHANGE COLUMN `title` `title` VARCHAR(45) NULL DEFAULT ''AFTER `course_id`,

CHANGE COLUMN `serialNumber` `serial_number` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '唯一标示码',

CHANGE COLUMN `tsaCount` `tsa_count` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '剩余确权次数'', Error_code: 1146

2019-07-11 15:05:12 17674 [Warning] Slave: Table 'api.ring_king_record' doesn't exist Error_code: 1146

2019-07-11 15:05:12 17674 [ERROR] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'mysql-bin.000762' position 16412436.2019-07-11 15:05:12 17674 [Note] Slave I/O thread: connected to master 'xxxx',replication started in log 'mysql-bin.000763' at position 2157463

可以很清晰的看到错误的原因是 api.ring_king_record 这个表根本不存在,但是却尝试去操作 change column 的操作。所以 slave 直接崩溃了, MySQL 提示我们数据库已经停止同步希望我们修复了这个问题之后再使用 SLAVE START 来启动 slave 的同步跟上 master.

这里只需要关注两个地方

1. mysql-bin.000762 可以让我们定位到发生问题是哪个 binlog。

2. position 可以让我们定位到发生的位置是在哪儿。

通过 position 16412435 如果你可以访问 master 物理机,那么可以通过访问 binlog 所在目录使用命令

mysqlbinlog mysql-bin.000672 | grep -C 100 16412435

去查看相关的信息,包括前后是什么语句,之类的。

如果类似于使用了 rds 这样的 MySQL 服务,可以去 master 所在的 rds 并使用 MySQL Client 上执行语句

show binlog events in 'mysql-bin.000762' from 16412436 limit 10\G;

我们可以得到从崩溃该语句开始的一些信息

mysql> show binlog events in 'mysql-bin.000762' from 16412436 limit 10\G;*************************** 1. row ***************************Log_name: mysql-bin.000762Pos:16412436Event_type: Gtid

Server_id:1215612563End_log_pos:16412484Info: SET @@SESSION.GTID_NEXT= '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038123'

*************************** 2. row ***************************Log_name: mysql-bin.000762Pos:16412484Event_type: Query

Server_id:1215612563End_log_pos:16412989Info: use `api`; ALTER TABLE `api`.`ring_king_record`

CHANGE COLUMN `course_id` `course_id` VARCHAR(45) NULL DEFAULT ''AFTER `id`,

CHANGE COLUMN `title` `title` VARCHAR(45) NULL DEFAULT ''AFTER `course_id`,

CHANGE COLUMN `serialNumber` `serial_number` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '唯一标示码',

CHANGE COLUMN `tsaCount` `tsa_count` VARCHAR(45) CHARACTER SET 'latin1' NULL DEFAULT '' COMMENT '剩余确权次数'

*************************** 3. row ***************************Log_name: mysql-bin.000762Pos:16412989Event_type: Gtid

Server_id:1215612563End_log_pos:16413037Info: SET @@SESSION.GTID_NEXT= '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038124'

*************************** 4. row ***************************Log_name: mysql-bin.000762Pos:16413037Event_type: Query

Server_id:1215612563End_log_pos:16413277Info:/*rds internal mark*/CREATE TABLE IF NOT EXISTS mysql.ha_health_check (

id BIGINT DEFAULT0,

type CHAR(1) DEFAULT '0',

PRIMARY KEY (type)

这里可以很清楚的看到崩溃位置 16412436 GTID: 8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038123 执行了 change column 的操作导致了崩溃。

现在我们要恢复 slave 就需要跳过这个报错的语句。因为全局开启了 GTID 的关系我们无法使用传统的

root@(none) >stop slave;

Query OK,0 rows affected (0.00sec)

root@(none)>SET GLOBAL SQL_SLAVE_SKIP_COUNTER =N; #跳过N个事务

Query OK,0 rows affected (0.00sec)

root@(none)>start slave;

Query OK,0 rows affected, 1 warning (0.03sec)

来恢复 会报错

ERROR1858 (HY000): sql_slave_skip_counter can not be set when the server is running with @@GLOBAL.GTID_MODE = ON. Instead, for each transaction that you want to skip, generate an empty transaction with the same GTID as the transaction

我在网上查了不少资料,但是感觉大部分都是互相 copy xjb 扯淡,也根本使用不了。

下面是我结合几个靠谱博客和官方文档写的一个配置

stop slave;

reset master;

reset slave;

CHANGE MASTER TO MASTER_HOST='master_address',MASTER_USER='xxx', MASTER_PASSWORD='xxx';set global gtid_purged = '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038123';

SET @@SESSION.GTID_NEXT= '8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038124';

begin;

commit;

SET GTID_NEXT="AUTOMATIC";

start slave;

下面我会依次介绍这些命令是用来干嘛的。

首先我们所有现在针对去恢复的 slave 操作都需要先停止 slave.

reset master 这一步我不是很确定是否真的可以不做,reset master 会将 slave 机器的所有 binlog 都清空。比如之前我们可能是 mysql-bin.000023 这样子,如果使用了 reset master 会重新从 mysql-bin.000001 开始记录 binlog。我因为清理了也没关系,因为我会要显示的指定我从 master 机器的什么位置开始消费并且追上 master 所以就设置了。

reset slave 将让 slave 忘记主从复制的关系的位置信息,它会删除 master.info 和 relay-log.iinfo 文件重置 relaylog 信息。我们知道 relay-log 其实就是用于记录 slave 复制 master 信息复制到哪里来了这里会重置这些信息。

然后我哦们指定 change master 重新指定我们要跟随的 master 地址。

设置全局的 gtid_purged 这里注意 这个 gtid_purged 用于告诉你的 slave 无视哪些 gtid 的记录段,就是我们会无视掉所有之前我们消费过的记录段直到到达我们报错的位置。这个可以跟下面的参数联动。从上面的图我们看到我们只需要跳过 change column 那条语句所在的 GTID 重新从

8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038124

开始消费即可跳过,所以上面我们使用 30038124-1 来表示我们需要 purged 的部分。

最后我们通过提交一个空事务并指定自动位移 GTID 来恢复我们的 slave。

一切完成之后我们启动 slave 使用 start slave

这个时候我们的 slave 从库会从我们指定的位置开始追上 master 只需要等待一段时间即可,那么如何判断已经追上了 master 呢?

我们在从库上执行

show slave status

mysql>show slave status\G;*************************** 1. row ***************************Slave_IO_State: Waitingfor master to send eventMaster_Host: xxxxxxxxxxxxMaster_User: xxxx

Master_Port:3306Connect_Retry:60Master_Log_File: mysql-bin.000764Read_Master_Log_Pos:6362259Relay_Log_File: mysqld-relay-bin.000006Relay_Log_Pos:6362469Relay_Master_Log_File: mysql-bin.000764Slave_IO_Running: Yes

Slave_SQL_Running: Yes

Replicate_Do_DB: xxxxxxxxxxxx

Replicate_Ignore_DB: mysql

Replicate_Do_Table:

Replicate_Ignore_Table:

Replicate_Wild_Do_Table:

Replicate_Wild_Ignore_Table:

Last_Errno:0Last_Error:

Skip_Counter:0Exec_Master_Log_Pos:6362259Relay_Log_Space:6362761Until_Condition: None

Until_Log_File:

Until_Log_Pos:0Master_SSL_Allowed: No

Master_SSL_CA_File:

Master_SSL_CA_Path:

Master_SSL_Cert:

Master_SSL_Cipher:

Master_SSL_Key:

Seconds_Behind_Master:0Master_SSL_Verify_Server_Cert: No

Last_IO_Errno:0Last_IO_Error:

Last_SQL_Errno:0Last_SQL_Error:

Replicate_Ignore_Server_Ids:

Master_Server_Id:1215612563Master_UUID: 8dcfd361-10cb-11e9-9060-506b4b2ac23e

Master_Info_File:/var/lib/mysql/master.info

SQL_Delay:0SQL_Remaining_Delay: NULL

Slave_SQL_Running_State: Slave has read all relay log; waitingfor the slave I/O thread to update it

Master_Retry_Count:86400Master_Bind:

Last_IO_Error_Timestamp:

Last_SQL_Error_Timestamp:

Master_SSL_Crl:

Master_SSL_Crlpath:

Retrieved_Gtid_Set: 8dcfd361-10cb-11e9-9060-506b4b2ac23e:30038448-30142673Executed_Gtid_Set: 0cf0e744-f9f6-11e8-bb7a-00163e302177:1-27887,

8dcfd361-10cb-11e9-9060-506b4b2ac23e:1-30142673Auto_Position:1

比较 Read_Master_Log_Pos 和 Exec_Master_Log_Pos 差不多就说明已经追上了 master。

Relay_Log_Pos 和他们差不多能说明 io 线程也能拉到最新的数据。

当我们有错误的时候 show slave status 也可以给我们提供非常多的信息,例如最后出错的信息是啥。为什么报错都有显示,如果没有第一时间去看错误日志,使用命令在这里看错误信息也不错。

另外使用 show variables like '%gtid%'; 也可以给我们提供一些基于 gtid 的信息。

唔。。。又是修数据跑监控的一天=。=

---------------------------------分割线---------------------------------

关于 GTID 昨晚回去 我重新翻看了一些资料觉得还是有必要多说两句。

可以说 GTID 的出现解决了之前完全依赖 master 文件和 pos 的来切换主从的问题得到了解决。

MySQL 版本5.6 引入了 GTID 解决主从同步位点问题。GTID 的全称是 Global Transaction Identifier 也就是全局事务 ID,是一个事务在提交的时候生成的,是这个事务的唯一标识。它由两部分组成:

GTID=server_uuid:gno

其中 server_uuid 是一个实例第一次启动时自动生成的,可以通过我们上面介绍的命令 show master/slave status 看到该机器的 UUID

gno 是一个整数,初始化是1,每次提交事务的时候分配给这个事务,并加 1。

GTIO 模式的启动配置:

#GTID

gtid_mode=on

enforce_gtid_consistency=on

log-slave-updates=1

GTID_mode 开启的参数相关的是前两个参数, log-slave-updates = 1 是开启连贯复制 log

本身 slave 同步 master 的日志是不会再放入自己的 binlog 中的,如果我们还有机器在监听 slave 的 binlog 日志就需要开启 log-slave-updates 参数。

在 GTID 模式下,每个事务都会跟一个 GTID 一一对应。这个 GTID 有两种生成方式,而使用哪种取决于 session 变量 gtid_next 的值。

可以看到上面我们在跳过事务的时候是直接指定了一个 GTID_NEXT 的位置从这个位置开始。

然后指定下面的偏移规则是 gtid_next=automatic 使用默认值每执行一个事务就 +1

这样每个 MySQL 实例都维护了一个 GTID 集合,用来对应“这个实例执行过的所有事务”。

因为这个集合的存在,所以我们在重制  slave 和 master 的进度的时候,如果 slave 并没有通过 gtid_purged 或者通过指定 GTID_NEXT 跳过已经执行的事务 slave 会尝试去执行这些事务,并且因为主键冲突等原因报错崩溃。

所以现在回头过来看这几条命令

set gtid_next='aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10';

begin;

commit;set gtid_next=automatic;

start slave;

其实它的意义是 首先 :10 这个gtid 是有问题那个 GTID 就是执行了会崩溃的那个 GTID 。

然后这个时候我们对其替换成一个空事务。

再设置之后都正常加一偏移数据。

最后启动 slave 。这样的话当我们的 slave 运行到这里的时候会因为已经因为这个 GTID 执行了空事务,而无视跳过 master 传递过来的有问题的 binlog 从而达到跳过有问题事务的目的。

由于没有实操过主备切换,这里注意到资料大部分都提到 GTID 模式下只需要指定 change master to 新的机器即可。新的 master 会自动计算相关的位点。

CHANGE MASTER TO MASTER_HOST='xxxx',MASTER_USER='xxx', MASTER_PASSWORD='xxx';

master_auto_position=1

Reference:

https://yq.aliyun.com/articles/155827  MySQL GTID 主从复制错误修复方法

https://www.douban.com/note/446551760/RESET MASTER 和RESET SLAVE 命令的使用方法 注意事项

https://www.cnblogs.com/zhoujinyi/p/4717951.html  MySQL5.6 新特性之GTID

mysql slave lock 跳过_处理 MySQL 因为 SLAVE 崩溃导致需要手动跳过 GTID 的问题 | 关于 GTID...相关推荐

  1. mysql slave 线程 简书_【MySQL】你真的读懂了slave status吗?

    前言:大家平时在检查主从复制的时候基本上都会使用 show slave status来看主从复制的情况,那么你真的读懂每个指标项了吗? 一.status指标解读 root@localhost [(no ...

  2. mysql从节点放家里_添加MySQL 5.6 从节点 Slave

    mysql版本:5.6.36 xtraback版本:version 2.4.6 1.修改主节点MySQL配置文件,并重启MySQL cat /usr/local/mysql/my.cnf [mysql ...

  3. mysql死锁释放时间参数_【Mysql】mysql 事务未提交导致死锁 Lock wait timeout exceeded; try restarting transaction 解决办法...

    问题场景 问题出现环境: 1.在同一事务内先后对同一条数据进行插入和更新操作: 2.多台服务器操作同一数据库: 3.瞬时出现高并发现象: 不断的有一下异常抛出,异常信息: org.springfram ...

  4. linux备份mysql需要暂停服务吗_【MySQL运维】线上MySQL数据库停服迁移流程

    一.数据备份与恢复阶段,选在凌晨1点进行操作,暂停服务进行备份(允许停服2个小时) 1.首先停止Nginx服务,并且修改数据库用户密码,防止还有新的连接进来 2.杀掉某个用户所有进程 for i in ...

  5. mysql MDL锁如何解决_理解MySQL的MDL元数据锁

    一.MDL锁的作用 MySQL DBA 对于 Waiting for table metadata lock 肯定不会陌生,一般都是进行 alter 操作时被堵住了,导致了我们在 show proce ...

  6. mysql 自动化运维工具_部署MySQL自动化运维工具inception+archer

    *************************************************************************** 部署MySQL自动化运维工具inception+ ...

  7. mysql数据库可以升级吗_[数据库]MySQL升级

    [数据库]MySQL升级 0 2016-08-16 22:00:18 MySQL的升级相对来说还是比较简单的. 它支持两种方式的升级: 原地升级(In-place Upgrade) 关闭数据库,替换旧 ...

  8. mysql的sql执行原理图_性能测试MySQL之SQL运行原理

    一,MySQL运行原理 两个一样的图 1,SQL语句执行的过程详细说明 如上图所示,当向MySQL发送一个请求的时候,MySQL到底做了什么: a, 客户端发送一条查询给服务器. b, 服务器先检查查 ...

  9. keepalived mysql双主架构图_基于MySQL双主的高可用解决方案理论及实践

    MySQL在互联网应用中已经遍地开花,但是在银行系统中,还在生根发芽的阶段.本文记录的是根据某生产系统实际需求,对数据库高可用方案从需求.各高可用技术特点对比.实施.测试等过程进行整理,完善Mysql ...

最新文章

  1. SD从零开始16 促销计划(Agreements)
  2. python保存数据_Python 保存数据的方法(4种方法)
  3. 整合tomcat的一些配置
  4. 深度学习:又一次推动AI梦想(Marr理论、语义鸿沟、视觉神经网络、神经形态学)
  5. 图论算法》关于SPFA和Dijkstra算法的两三事
  6. java实现base64加密解密
  7. DataReader不奇怪,该出手时就出手!
  8. shell中循环执行某个进程获取返回值,并循环执行直到函数出错
  9. resnext50_32x4d-inference
  10. SpringMVC→拦截器、SpringMVC拦截器实现、多个拦截器工作原理、拦截器使用场景、拦截器Interceptor与过滤器Filter区别
  11. 软件工程毕设项目 - 基于SSM的房屋租赁系统(含源码+论文)
  12. 超级灰色按钮克星更新v1.3.1112.40
  13. WGS84坐标系转换到J2000坐标系
  14. Java和Android笔试题
  15. outlook qr码在哪里_聚合码微信支付宝申请开通,商家融合收款码实现一码支付,如何申请微信和支付宝合并收款码?聚合码支持信用卡、花呗、微信和支付宝收款...
  16. linux安装或更新显卡驱动
  17. 人性:《少年pi的奇幻漂流》和《一九四二》连看小感
  18. HTML+CSS美食静态网页设计
  19. Typo3 CVE-2019-12747 反序列化漏洞分析
  20. QuerySet浅尝

热门文章

  1. (经典)Hibernate多对一关系映射(四)
  2. hadoop学习--多表关联
  3. Python实现有道翻译
  4. matlab中的cellstr的用法,matlab中的cell array, cellstr()和char()的用法
  5. gis中dbf转为csv_Python中.dbf到.csv的批量转换
  6. python语言有几种编程方式_零基础自学python语言,有哪几种方法?龟叔说:这套教程带你入门...
  7. delphi memo 查找字符 下行插入_Vim高手,从来不用鼠标2——替换、撤销、缩进、查找
  8. 电子产品设计流程_产品设计“学习、就业、留学”全攻略
  9. Python入门100题 | 第006题
  10. QT 使用全局变量的方法