MYSQL主从同步异常汇总

问题描述:

程序上表现为对 主库 更新操作之后,从 从库 查询数据没发生改变。怀疑是主从库同步延迟导致。上从库查看主从同步状态,发现Seconds_Behind_Master时间长达一千多秒。正常情况下主从库延时个十几秒还可以容忍,一千多秒显然就有问题了么。。。

问题分析:

我们在一个MYSQL实例上创建了四五个Database,其中一个Database数据量和压力都比较大,从 从库的processlist可以看到从库在处理日志时经常发生lock的状况,但是lock只是压力大database为何会影响到其他database也延迟呢?

原来从库是单线程处理同步日志,也就是说无论多少个database都是通过一个线程去执行更新操作,所以主从库同步延迟的时间不是针对database的,是针对一个MYSQL实例的。

那么,为何从库在处理日志时会发生lock的状态呢?

一般我们都将主从库读写分离,主库负责写操作,从库负责读操作。而一般的web应用读数据的操作要远远大于写数据的量,所以我们在主库上几乎看不到因为更新数据导致的lock。那么从库的lock怎么发生的呢?

[c-sharp] view plain copy print ?
  1. 对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
  2. 对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。

从上面可以看出,我们在select的时候默认是会阻塞写请求的,当一个表数据量到达了千万级别,那么执行一个select很有可能就会变得比较费劲,再加上一定的压力,不断地select操作,虽然读数据不会受到影响,但是却阻塞了从库处理同步日志的操作。长此以往。。。可想而知。。。

问题处理:

1.首先一个MYSQL实例不要创建太多database,否则一旦其中一个库压力大经常被锁,会导致所有库同步都延迟,你伤不起啊。。。

2.压力较大的情况下使用几个从库值得考量,如果使用多个从库也是可以适当缓解上面lock的情况发生。


#################################

Mysql主从同步延迟与系统时间的关系

#################################################


ysql主从同步延迟受到多种因素影响, 比如大事务, 从库查询压力,网路延迟等; 这些比较常见; 但还受到主从机器系统时钟差的影响,这一点可能容易被忽视。
上周, 就遇到了这样的情况, 主库的系统时间由于某种原因落后于从库几十秒, 结果频繁的出现大的主从延迟同步,查了N久业务方面的问题,都找不出原因;在和同事的交流中,发现大家对参数Seconds_Behind_Master的理解有点补一样,基本有两种理解:

一种理解是来源于Mysql手册上的描述,大体意思是这个时间是从库SQL线程处理的最近的日志事件的时间戳减去从库IO线程处理的最近一条日志记录的时间戳得到的,可以简单理解为从库SQL线程与IO线程所处理的最近的日志事件的时间戳差;这个计算方式给人的感觉不是在计算主从延迟,而是在计算从库上两个线程的处理的日志的时差。
另一种理解来源于《High PerformaceMysql》上的的描述,大体意思这个参数反映的结果是当前系统时间减去从库IO线程所处理的最近一条日志记录的时间戳;但这个说法有一个明显的不太让人信服的地方,就是如果机器的系统时间相差比较大怎么办? 显然, 如果系统时间相差比较大的话,以这样的方式计算主从延迟毫无意义。

在有分歧的情况下, 去查看了一下Mysql的源代码, 结果发现手册上的描述居然不那么准确, 代码大致如下:
......if ((mi->slave_running ==MYSQL_SLAVE_RUN_CONNECT)&&mi->rli.slave_running){

<wbr><wbr><wbr><wbr><wbr> long time_diff= ((long)(time(0) -mi-&gt;rli.last_master_timestamp)<wbr><wbr><wbr><wbr><wbr><wbr> -mi-&gt;clock_diff_with_master);<br><wbr><wbr><wbr><wbr><wbr>protocol-&gt;store((longlong)(mi-&gt;rli.last_master_timestamp?<wbr><wbr> max(0, time_diff) :0));<br><wbr><wbr><wbr><wbr><wbr> ......}else{<br><wbr><wbr><wbr><wbr><wbr> protocol-&gt;store_null();<br> }<br> 从代码看, 如果从库IO线程到主库的连接有问题或者SQL线程没有在运行, Seconds_Behind_Master直接返回NULL;否则的话,用从库当前系统时间减去IO线程处理的最近的事件的时间戳;代码里用mi-&gt;clock_diff_with_master来排除系统时间差对计算的影响,那这个值又是怎么计算来的呢? 继续看代码:<br><br> ......if (!mysql_real_query(mysql, STRING_WITH_LEN("SELECTUNIX_TIMESTAMP()")) &amp;&amp;(master_res=mysql_store_result(mysql))&amp;&amp;(master_row=mysql_fetch_row(master_res))){<wbr><wbr><wbr><wbr><wbr><wbr> mi-&gt;clock_diff_with_master=<wbr> (long) (time((time_t*) 0) -strtoul(master_row[0], 0, 10));}else if(!check_io_slave_killed(mi-&gt;io_thd, mi,NULL)){<wbr><wbr><wbr><wbr><wbr><wbr> mi-&gt;clock_diff_with_master= 0;<wbr><wbr><wbr><wbr><wbr><wbr> ......}<br><br> 原来这个值是通过在主库上执行SELECT UNIX_TIMESTAMP()来取得主库的系统时间,然后去减从库的当前系统时间。<br><br> 原来系统时间差还真的对主从同步延迟参数Seconds_Behind_Master有影响。<br> 转载:<a href="http://hi.baidu.com/zhencaishu/blog/item/355f8c1078d537f5c2ce79c2.html" target="_blank" name="url_1">http://hi.baidu.com/zhencaishu/blog/item/355f8c1078d537f5c2ce79c2<wbr>.html</wbr></a><br> 在今天的一次主从部署中,发现主从库所在系统时间差别较大时(差别20天左右),同步的性能也非常差。但没有找到证据,暂且如此怀疑,以后留意</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

问题描述:

程序上表现为对 主库 更新操作之后,从 从库 查询数据没发生改变。怀疑是主从库同步延迟导致。上从库查看主从同步状态,发现Seconds_Behind_Master时间长达一千多秒。正常情况下主从库延时个十几秒还可以容忍,一千多秒显然就有问题了么。。。

问题分析:

我们在一个MYSQL实例上创建了四五个Database,其中一个Database数据量和压力都比较大,从 从库的processlist可以看到从库在处理日志时经常发生lock的状况,但是lock只是压力大database为何会影响到其他database也延迟呢?

原来从库是单线程处理同步日志,也就是说无论多少个database都是通过一个线程去执行更新操作,所以主从库同步延迟的时间不是针对database的,是针对一个MYSQL实例的。

那么,为何从库在处理日志时会发生lock的状态呢?

一般我们都将主从库读写分离,主库负责写操作,从库负责读操作。而一般的web应用读数据的操作要远远大于写数据的量,所以我们在主库上几乎看不到因为更新数据导致的lock。那么从库的lock怎么发生的呢?

[c-sharp] view plain copy print ?
  1. 对MyISAM表的读操作(加读锁),不会阻塞其他进程对同一表的读请求,但会阻塞对同一表的写请求。只有当读锁释放后,才会执行其它进程的写操作。
  2. 对MyISAM表的写操作(加写锁),会阻塞其他进程对同一表的读和写操作,只有当写锁释放后,才会执行其它进程的读写操作。

从上面可以看出,我们在select的时候默认是会阻塞写请求的,当一个表数据量到达了千万级别,那么执行一个select很有可能就会变得比较费劲,再加上一定的压力,不断地select操作,虽然读数据不会受到影响,但是却阻塞了从库处理同步日志的操作。长此以往。。。可想而知。。。

问题处理:

1.首先一个MYSQL实例不要创建太多database,否则一旦其中一个库压力大经常被锁,会导致所有库同步都延迟,你伤不起啊。。。

2.压力较大的情况下使用几个从库值得考量,如果使用多个从库也是可以适当缓解上面lock的情况发生。

你可能感兴趣的:(Mysql主从)