mysql常见slave延迟原因有哪些

38次阅读
没有评论

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

这篇文章主要介绍了 mysql 常见 slave 延迟原因有哪些,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让丸趣 TV 小编带着大家一起了解一下。

一   序言

在运维线上 M -M 架构的 MySQL 数据库时, 接收的比较多关于主备延时的报警:

check_ins_slave_lag (err_cnt:1)critical-slavelag on ins:3306=39438

相信 slave 延迟是 MySQL dba 遇到的一个老生长谈的问题了。先来分析一下 slave 延迟带来的风险

  1. 异常情况下, 主从 HA 无法切换。HA 软件需要检查数据的一致性,延迟时,主备不一致。 

  2. 备库复制 hang 会导致备份失败 (flush tables with read lock 会 900s 超时)

  3. 以 slave 为基准进行的备份,数据不是最新的, 而是延迟。

二   如何解决

面对此类问题我们如何解决,如何规避?分析一下导致备库延迟的几种原因

1. ROW 模式无主键、无索引或索引区分度不高. 有如下特征

   a. show slave status 显示 position 一直没有变

   b. show open tables 显示某个表一直是 in_use 为 1

   c. show create table 查看表结构可以看到无主键,或者无任何索引,或者索引区分度很差。

解决方法:

   a. 找到表区分度比较高的几个字段, 可以使用这个方法判断:

    select count(*) from xx; 

    select count(*) from (select distinct xx from xxx) t;

    如果 2 个查询 count(*) 的结果差不多,说明可以对这些字段加索引

   b. 备库 stop slave;

    可能会执行比较久,因为需要回滚事务。

  c. 备库

    set sql_log_bin=0;

    alter table xx add key xx(xx);

  老的版本 slave 应用 binlog 时只会选择第一个索引,需要把新加的索引放在最前面,可以先把老的索引删掉,建新的索引,再把老的索引建上。可以放到一个 sql 中执行。

  d. 备库 start slave

    如果是 innodb, 可以通过 show innodb status 来查看 rows_inserted,updated,deleted,selected 这几个指标来判断。

    如果每秒修改的记录数比较多,说明复制正在以比较快的速度执行。

2 MIXED 模式无索引或 SQL 慢

    在从库上 show full processlist 查看到正在执行的 SQL。

解决方法:

  a.  SQL 比较简单, 则检查是否缺少索引,并添加索引。

  b. 另一类是 insert into select from 的语句,如果 select 里包含 group by,多表关联,可能效率会比较低。

      这类可以到主库把 binlog_format 改成 row。

3 主库上有大事务, 导致从库延时

现象解析 binlog 发现类似于下图的情况看

解决方法:

与开发沟通, 增加缓存, 异步写入数据库, 减少直接对 db 的大量写入。

4. 主库写入频繁, 从库压力跟不上导致延时

  此类原因的主要现象是数据库的 IUD 操作非常多,slave 由于 sql_thread 单线程的原因追不上主库。

  解决方法:

 a 升级从库的硬件配置, 比如 ssd,fio.

 b 使用 @丁奇的预热工具 -relay fetch

    在备库 sql 线程执行更新之前,预先将相应的数据加载到内存中, 并不能提高 sql_thread 线程执行 sql 的能力,也不能加快 io_thread 线程读取日志的速度。

 c 使用多线程复制 阿里 MySQL 团队实现的方案 – 基于行的并行复制。

    该方案允许对同一张表进行修改的两个事务并行执行,只要这两个事务修改了表中的不同的行。这个方案可以达到事务间更高的并发度,但是局限是必须使用 Row 格式的 binlog。因为只有使用      Row 格式的 binlog 才可以知道一个事务所修改的行的范围,而使用 Statement 格式的 binlog 只能知道修改的表对象。

5. 数据库中存在大量 myisam 表,在备份的时候导致 slave 延迟

  由于 xtrabackup 工具备份到最后会执行 flash tables with read lock,对数据库进行锁表以便进行一致性备份,然后对于 myisam 表 锁,会阻碍 salve_sql_thread 停滞运行进而导致 hang

该问题目前的比较好的解决方式是修改表结构为 innodb 存储引擎的表。

  三   拓展阅读

 [1]  怎样解决 MySQL 数据库主从复制延迟的问题  

 [2]  三种 MySQL 并行复制方案的分析                

 [3]  一种 MySQL 主从同步加速方案-改进

 [4] MySQL 多线程同步 MySQL-Transfer 介绍

6、如何确认真正延迟多少?
seconds_bebind_master 这个参数不准,有时显示为 0,但是有数据延迟的情况,在 stop slave 和 start slave 后,数据就同步过来了,因为 slave 有时候检测网络正常失败,可以使用脚本来实现监控,在 salve 和 master 节点分别部署。
先在两个节点都创建监控表

span  >

#encoding=gbk 

import datetime,time 

import os,sys 

from public import db 

 

import db_conf 

 

source_folder = db_conf.SOURCE_FOLDER 

 

 

def init_eviroment_path(): 

 print sys.path 

 python_path = (source_folder) 

 

 for i in python_path: 

 if i not in sys.path: 

 sys.path.append(i) 

 

 print sys.path 

 

def main(): 

 conn, cursor = db.GetMysqlCursor(update) 

 

 cursor.execute(insert into heartbeat (master_datetime,slave_datetime) values(now(),sysdate()) ) 

 

 cursor.close() 

 conn.close() 

 

if __name__ ==  __main__ : 

 init_eviroment_path() 

 os.system(title MySQL Replication 心跳) 

 count = 1 

 while True: 

 main() 

 print  (%d)%s %(count,datetime.datetime.now()) 

 count+=1 

 time.sleep(60) span  >

 

修改 master 端的 binlog 模式为 statement(默认为 mix)

所以这么修改是因为必须是 statement 的 SQL 语句同步模式才行,否则 mix 下有可能是 ROW 的结果数据同步模式就不行,这个我也是通过 master show binlog events 才找到这个原因。

如果要立刻看到结果,只要把 master 端的时间修改一下,例如提前一个小时,执行:

insert into heartbeat (master_datetime,slave_datetime) values(now(),sysdate()) 在 slave 上就可以看到类似如下结果:

感谢你能够认真阅读完这篇文章,希望丸趣 TV 小编分享的“mysql 常见 slave 延迟原因有哪些”这篇文章对大家有帮助,同时也希望大家多多支持丸趣 TV,关注丸趣 TV 行业资讯频道,更多相关知识等着你来学习!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-26发表,共计3124字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)