1.版本
1)操作系统
cat /etc/issue
Red Hat Enterprise Linux Server release 5.5 (Tikanga)
Kernel \r on an \m
cat /proc/version
Linux version 2.6.32-504.el6.x86_64 ([email protected]) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Wed Oct 15 04:27:16 UTC 2014
2)mysql数据库版本
mysql --version
mysql Ver 14.14 Distrib 5.6.26, for linux-glibc2.5 (x86_64) using EditLine wrapper
2.问题描述
2.1 发现问题
1)收到生产库的某个从库告警,登录从库 show slave status\G;进行查看,发现如下错误:
Last_Error: Slave SQL thread retried transaction 10 time(s) in vain, giving up. Consider raising the value of the slave_transaction_retries variable.2)查看从库的errorlog,发现有如下错误:(敏感信息我使用xx替换了)
2016-03-07 16:20:19 8349 [Warning] Slave SQL: Error 'Lock wait timeout exceeded; try restarting transaction' on query. Default database: 'oms_orders'. Query: 'INSERT INTO table1 (xx,xx,xx,xx,xx,xx,xx,xx,xx) VALUES('xx','xx','xx','','x','x','xx','xx','x') ON DUPLICATE KEY UPDATE class_id='xx',parent_class_id='x',class_name='xx',class_desc='',map_id='x',contains_metaclass='0',sort='10000',property='262144',state='0'', Error_code: 1205##errorlog中如上的错误一共报了10次(因为slave_transaction_retries默认值为10),也就是说在1025错误发生10次以后,从库的Slave_SQL_Running变为NO,并报如上1)中错误。
3. 问题分析
通过从库的errorlog我们可以判断是有什么事物阻塞了 从库的 insert into table1操作,从而导致insert into table1 操作等待加锁超发生超时。根据这个思路跟研发问了一下当时他们在从库上做了什么操作没有。果然他们正好在那个时间点对table1 进行操作。他们的操作可以概括为如下:
create temporary table test1 select * from table1 where;(当然他们的语句复杂很多对同一个表table1进行了多次关联)这个操作执行完需要很长时间。
##ok 分析到现在问题已经很清楚了,是因为研发的create temporary table test1 select * from table1 where ;(会加next-key locks)操作阻塞了 insert into table1 操作。(按照这个思路,在测试环境也重现了该问题)
##注意本篇博客描述的只是该报错的一种可能,该报错也有可能是其他某些原因导致的(没有深入研究)
4. 问题追加
上面从库的报错已经搞清楚了,但是可能细心的朋友有会疑问。怎么在从库上能够建表?
有人可能会说因为从库没有设置read-only为on,还有可能研发用的用户具有super权限。答案呢?,从库已经设置了 read_only,研发使用的也是普通用户没有super权限。 有兴趣的朋友可以试一下在从库上建如下用户,然后使用该用户创建执行 create table和create temporary table
grant select,create,create temporary tables on *.* to 'test1'@'xxxx' identified by 'xxxx';
mysql> create table test1 select * from test; ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement##我们可以看到设置了read_only为on的情况下,在从库建普通表会报错。
mysql> create temporary table test1 as select * from test; Query OK, 3 rows affected (0.18 sec) Records: 3 Duplicates: 0 Warnings: 0##在read_only为on的情况下,test用户在从库执行create temporary table 成功。