MySQL复制中的管理技巧

复制中断处理

  • 1677错误
    • 第一种将主库改成statement格式
    • 第二种在从库设置slave_type_conversions
  • 从库出现写入数据,把自增ID占用:1062错误
    • 将从库该条数据删除
    • 能确定数据一致也可以跳过该错误
  • 从库上出现少数据,delete,update操作时,找不到相应的记录,出现1032错误
    • delete可以跳过错误
    • update只能补数据,在master的binlog中解析出哪个位置出错了,将这条数据插入,主要是主键个非空列,开启复制sql_thread,查看status
  • 从库gtid值大于主库gtid值
    • 有可能主库被reset了
    • 新回复的从库将auto.cnf也恢复了,binlog还删除了,也有可能会出现这种场景

复制延迟排查

  • 搞明白当前的数据库在干什么
    • show processlist;
    • show slave status\G定位到sql_thread执行到位置
      • io_tread同步到主库的binlog位置:Master_Log_File;Read_Master_Log_Pos
      • sql_thread重放到对应主库的binlog位置:Relay_Master_Log_File;Exec_Master_Log_Pos
      • Seconds_Behind_Master:这个值是怎么计算的?
        • io_thread.event.timestamp-sql_thread.event.timestamp 单位秒
  • 查看当前的SQL状态
    • 机器负载很高
      • 索引不合理!!!
      • Statement索引不合理,造成同步延迟
        • mysql>pager more
        • mysql>show processlist;
          • 可以直接用select * from information_schema.processlist where 1=1 order by TIME desc limit 10;
          • USER不是sys的,感觉没什么问题的,时间太长快死掉的连接都可以杀掉
        • 在从库上能看到执行的SQL都有问题的!!!
  • 利用perf top 查看MySQL的调度情况
    • perf top -p `pidof mysqld`
    • 利用Google
    • 利用源码定位出问题的地方
  • 延迟现象一
    • Seconds_Behind_Master一直在增大,但Exec_master_log_pos就是卡着不动
    • 解析sql_thread执行的binlog
    • mysqlbinlog -v --base64-output=decode=rows --start-position=xxx mysql-bin.xxxx
    • 去主库上面找
      • Relay_Master_Log_File,Exec_Master_Log_Pos这两个参数定位
    • 在从库上面找
      • Relay_Log_File,Relay_Log_Pos这两个参数
    • 大事务卡的两个原因
      • 真的是大事务等待,一次更新50W行以上,坐等
      • 更新这个表可能没有索引
        • stop slave不了可以mysqladmin -S/mysql3306.sock shutdown
        • 关闭都关闭不了,只能kill -9,从库这么干,主库还是不要这么干
        • 重启mysql,重建索引,之后start slave

如何避免延迟

  • 从库的配置适当高一点
  • 使用MySQL5.7开启并行复制
  • 表结构设计时,一定要有主键,而且主键要短小
  • 使用新型硬件:PCI-E&SSD类设备
  • 程序端适当的Cache,减少数据库的压力

复制结构调整Tips

  • 场景
  • 将下图中的机器加内存,并修改buffer pool,业务暂停时间小于1分钟


    MySQL复制中的管理技巧_第1张图片
  • 凌晨读写压力不大的情况下,可以考虑将读写都放在M上
  • 将s1->stop slave;
  • s1,s11,s12,s13全部shutdown,加内存,修改buffer pool
  • 在s1和M上装keepalived,vip先指到M上,之后停掉M,查看vip是否指到s1上
  • 如果是gtid复制,M启动后直接change master指到s1就可以
    • 在将s11,s13,M都指向s12就ok了
  • 如果是传统复制,要经过一下几步
    • 在vip指过去之前在s1上执行show master status;
    • sleep 1;
    • show master status;结果没变化可以将结果保存到一个文件中
    • show master status>/tmp/1.log
    • M启动后change master to指s1就可以
    • 将s11,s13,M指向s12有两种办法
    • 第一种
      • 可以手工制造个错误,使s11,s12,s13,M都停在同一个位置
      • 在s12上执行show master status>/tmp/1.log
      • 在将s11,s13,M都指向s12就ok了
      • 之后再s12上跳过错误或者将错误修复
    • 第二种
      • 将s11,s12,s13,M全部停掉sql_thread
      • 在s1上执行show master status;
      • s11,s12,s13,M执行start slave sql_thread until master_log_file='xxx',master_log_pos=xxx;
      • 使s11,s12,s13,M机器都停在s1执行的show master status节点上
      • 在s12上执行show master status>/tmp/1.log
      • 在将s11,s13,M都指向s12就ok了
  • 将级联复制改成正常的一级复制


    MySQL复制中的管理技巧_第2张图片
  • gtid可以直接change过去
  • 传统复制
    • 在s1上执行stop slave;
    • 在s1上查看show slave status;
    • 在s11上的change master语句,host,port指定到M上
    • master_log_file='Relay_Master_Log_File' #在s1上执行show slave status查看出来的
    • master_log_pos=Exec_Master_Log_Pos #在s1上执行show slave status查看出来的
    • s2,s21同上
    • 将所有的从库开启复制start slave
  • 假设s1机器电源坏了,不能登录,将s11机器挂到M下或者挂到s2下,怎么搞定?
    • gtid可以直接change master过去
    • 传统复制
      • 一种是将s21机器复制一份数据将s11机器还原,挂到s2下
      • 另一种是不需要重新备份
        • 解析s21机器的mysql-binlog,找到最后一个M库的server_id对应的事务,在这个事务上面找到它对应的timestamp,开启中继日志情况下server_id和timestamp具有传递性
        • 解析出timestamp对应的时间,去M机器上面找到对应的mysql-binlog,大概找到这个时间是写入的哪个binlog,可以用ls查看
        • 解析这个binlog,在这个binlog中查找上述的timestamp,找到对应的事务,要和从库上的那个事务语句一样才可以,查看一下从库的这个事物执行完没有(commit还是没commit),如果没执行完就要记录这个事物begin之前的log_pos,执行完了就记录下一个事务开始的log_pos
        • 将上述的binlog和log_pos写入到从库的change master to上面,开启复制,就可以将机器挂到M下面了

你可能感兴趣的:(MySQL复制中的管理技巧)