Chinaunix首页 | 论坛 | 博客
  • 博客访问: 31250
  • 博文数量: 12
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 177
  • 用 户 组: 普通用户
  • 注册时间: 2014-12-09 10:25
个人简介

我叫陆哥,一位热爱学习,热爱分享营销案例、裂变营销、商业模式的斜杠青年。

文章分类

全部博文(12)

文章存档

2019年(1)

2014年(11)

我的朋友

分类: Mysql/postgreSQL

2014-12-15 10:08:24

在MySQL复制环境中,我们通常只根据 Seconds_Behind_Master 的值来判断SLAVE的延迟。这么做大部分情况下尚可接受,但并不够准确,而应该考虑更多因素。

首先,我们先看下SLAVE的状态:

  1. yejr@imysql.com [(none)]> show slave status\G
  2. *************************** 1. row ***************************
  3. Slave_IO_State: Waiting for master to send event
  4. ***
  5. Master_Log_File: mysql-bin.000327
  6. Read_Master_Log_Pos: 668711237
  7. Relay_Log_File: mysql-relay-bin.002999
  8. Relay_Log_Pos: 214736858
  9. Relay_Master_Log_File: mysql-bin.000327
  10. Slave_IO_Running: Yes
  11. Slave_SQL_Running: Yes
  12. ***
  13. Skip_Counter: 0
  14. Exec_Master_Log_Pos: 654409041
  15. Relay_Log_Space: 229039311
  16. ***
  17. Seconds_Behind_Master: 3296
  18. ***

可以看到 Seconds_Behind_Master 的值是 3296,也就是SLAVE至少延迟了 3296 秒。

我们再来看下SLAVE上的2个REPLICATION进程状态:

  1. yejr@imysql.com [(none)]> show full processlist\G
  2. *************************** 1. row ***************************
  3. Id: 6
  4. User: system user
  5. Host:
  6. db: NULL
  7. Command: Connect
  8. Time: 22005006
  9. State: Waiting for master to send event
  10. Info: NULL
  11. *************************** 2. row ***************************
  12. Id: 7
  13. User: system user
  14. Host:
  15. db: NULL
  16. Command: Connect
  17. Time: 3293
  18. State: Updating
  19. Info: UPDATE ** SET ** WHERE **

可以看到SQL线程一直在执行UPDATE操作,注意到 Time 的值是 3293,看起来像是这个UPDATE操作执行了3293秒,一个普通的SQL而已,肯定不至于需要这么久。 实际上,在REPLICATION进程中,Time 这列的值可能有几种情况:

1、SQL线程当前执行的binlog(实际上是relay log)中的timestamp和IO线程最新的timestamp的差值,这就是通常大家认为的 Seconds_Behind_Master 值,并不是某个SQL的实际执行耗时;

2、SQL线程当前如果没有活跃SQL在执行的话,Time值就是SQL线程的idle time;

而IO线程的Time值则是该线程自从启动以来的总时长(多少秒),如果系统时间在IO线程启动后发生修改的话,可能会导致该Time值异常,比如变成负数,或者非常大。

来看下面几个状态:
#设置pager,只查看关注的几个status值

  1. yejr@imysql.com [(none)]> pager cat | egrep -i 'system user|Exec_Master_Log_Pos|Seconds_Behind_Master|Read_Master_Log_Pos'
#这是没有活跃SQL的情况,Time值是idle time,并且 Seconds_Behind_Master 为 0
  1. yejr@imysql.com [(none)]> show processlist; show slave status\G
  2. | 6 | system user | | NULL | Connect | 22004245 | Waiting for master to send event | NULL |
  3. | 7 | system user | | NULL | Connect | 13| Has read all relay log;**
  4. Read_Master_Log_Pos: 445167889
  5. Exec_Master_Log_Pos: 445167889
  6. Seconds_Behind_Master: 0
#和上面一样
  1. yejr@imysql.com [(none)]> show processlist; show slave status\G
  2. | 6 | system user | | NULL | Connect | 22004248 | Waiting for master to send event | NULL |
  3. | 7 | system user | | NULL | Connect | 16 | Has read all relay log;**
  4. Read_Master_Log_Pos: 445167889
  5. Exec_Master_Log_Pos: 445167889
  6. Seconds_Behind_Master: 0
#这时有活跃SQL了,Time值是和 Seconds_Behind_Master 一样,即SQL线程比IO线程“慢”了1秒
  1. yejr@imysql.com [(none)]> show processlist; show slave status\G
  2. | 6 | system user | | NULL | Connect | 22004252 | Waiting for master to send event | NULL |
  3. | 7 | system user | | floweradmin | Connect | 1| Updating | update **
  4. Read_Master_Log_Pos: 445182239
  5. Exec_Master_Log_Pos: 445175263
  6. Seconds_Behind_Master: 1
#和上面一样
  1. yejr@imysql.com [(none)]> show processlist; show slave status\G
  2. | 6 | system user | | NULL | Connect | 22004254 | Waiting for master to send event | NULL |
  3. | 7 | system user | | floweradmin | Connect | 1| Updating | update **
  4. Read_Master_Log_Pos: 445207174
  5. Exec_Master_Log_Pos: 445196837
  6. Seconds_Behind_Master: 1

好了,最后我们说下如何正确判断SLAVE的延迟情况:

1、首先看Relay_Master_Log_FileMaster_Log_File 是否有差异;

2、如果Relay_Master_Log_FileMaster_Log_File 是一样的话,再来看Exec_Master_Log_PosRead_Master_Log_Pos 的差异,对比SQL线程比IO线程慢了多少个binlog事件;

3、如果Relay_Master_Log_FileMaster_Log_File 不一样,那说明延迟可能较大,需要从MASTER上取得binlog status,判断当前的binlog和MASTER上的差距;

因此,相对更加严谨的做法是: 在第三方监控节点上,对MASTER和SLAVE同时发起SHOW BINARY LOGSSHOW SLAVE STATUS\G的请求,最后判断二者binlog的差异,以及 Exec_Master_Log_PosRead_Master_Log_Pos 的差异。

例如: 在MASTER上执行SHOW BINARY LOGS 的结果是:

+------------------+--------------+
| Log_name | File_size |
+------------------+--------------+
| mysql-bin.000009 | 1073742063 |
| mysql-bin.000010 | 107374193 |
+------------------+--------------+

而在SLAVE上执行SHOW SLAVE STATUS\G 的结果是:
  1. Master_Log_File: mysql-bin.000009
  2. Read_Master_Log_Pos: 668711237
  3. Relay_Master_Log_File: mysql-bin.000009
  4. Slave_IO_Running: Yes
  5. Slave_SQL_Running: Yes
  6. ***
  7. Exec_Master_Log_Pos: 654409041

  8. ***
  9. Seconds_Behind_Master: 3296
  10. ***

这时候,SLAVE实际的延迟应该是: mysql-bin.000009 这个binlog中的binlog position 1073742063 和 SLAVE上读取到的binlog position之间的差异延迟,即:

1073742063 - 654409041 = 419333022 个binlog event 

并且还要加上 mysql-bin.000010这个binlog已经产生的107374193个binlog event,共

107374193 + 419333022 = 526707215 个binlog event

后记更新:

1、可以在MASTER上维护一个监控表,它只有一个字段,存储这最新最新时间戳(高版本可以采用event_scheduler来更新,低版本可以用cron结合自动循环脚本来更新),在SLAVE上读取该字段的时间,只要MASTER和SLAVE的系统时间一致,即可快速知道SLAVE和MASTER延迟差了多少。不过,在高并发的系统下,这个时间戳可以细化到毫秒,否则哪怕时间一致,也是有可能会延迟数千个binlog event的。

2、网友(李大玉,QQ:407361231)细心支出上面的计算延迟有误,应该是mysql-bin.000009的最大事件数减去已经被执行完的事件数,即1073742063 – 654409041= 419333022个binlog event,再加上mysql-bin.000010这个binlog已经产生的107374193个binlog event,共526707215 个binlog event。



出自imysql中文网


阅读(431) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~