首页 存档 技术 查看内容

一个参数救活被hang住的数据库!

2018-3-30 13:00 |来自: 互联网 250 0

摘要: 作者介绍 贺春,惠普金融MySQL专家,《MySQL管理之道》第一版、第二版作者。曾任职于中国移动飞信、机锋安卓市场,拥有丰富的数据库管理经验。目前致力于MySQL、Linux等开源技术的研究。 现象开年头一天上班,开发说 ...


作者介绍

贺春惠普金融MySQL专家,《MySQL管理之道》第一版、第二版作者。曾任职于中国移动飞信、机锋安卓市场,拥有丰富的数据库管理经验。目前致力于MySQL、Linux等开源技术的研究。


现象

开年头一天上班,开发说程序连接不上数据库了,程序伴随着有大量的update锁超时,试着引导他们用SQLYOG客户端连接均无问题,然后查看监控图发现有大量的锁,如下图:




排查

  • 数据库版本为:10.0.28-MariaDB-enterprise - MariaDB Enterprise Certified Binary

  • DELL R730XD 128G内存(BP 70G)/14块SAS 15000转RAID10

  • Update操作/秒30-50左右 innodb_lock_wait_timeout锁等待超时设置为10秒


在MySQL中information_schema库下有三个经典的数据字典表:INNODB_LOCK_WAITS、PROCESSLIST、INNODB_TRX,三者可以结合起来,就能够查到相对比较完整的阻塞信息和事务的情况。


1、通过以下SQL语句查看

SELECT
a.trx_id,
trx_state,
trx_started,
b.id AS thread_id,
b.info,
b.user,
b.host,
b.db,
b.command,
b.state
FROM
information_schema.`INNODB_TRX` a,
information_schema.`PROCESSLIST` b
WHERE a.trx_mysql_thread_id = b.id
ORDER BY a.trx_started;


查询结果如下:


请注意红色标识的,trx_state事务状态是RUNNING,但command那里查不到正在执行的SQL,显示的是Sleep状态。

2、通过以下SQL语句查看

SHOW ENGINE INNODB STATUS\G


查询结果如下:


请注意红色标识,事务ID和线程ID的状态为ACTIVE且运行了563秒,凭着以往处理故障的经验,这是N多条未提交事务的SQL引起的。


分析

当时慢查询日志里并没有记录慢SQL,线上设置的为1秒,询问开发是哪个SQL被锁了,也不清楚,说是通过框架生成的SQL语句,不好排查。

然后我们开启了general_log抓包,得到了很多简单的update,每次更新为1条记录,例如update t1 set name='aa' where id=XX,通过explain查看执行计划,where后面的字段都用到了索引,正常情况下执行这种SQL只需零点几毫秒的时间,但由于会话A对该记录更改未提交,会话B又对该记录进行更改,此时就会出现锁等待,直到超过了innodb_lock_wait_timeout参数设置的阈值。

在并发访问比较高的情况下,如果大量事务因无法立即获得所需的锁而挂起,会占用大量的连接数资源,造成严重的性能问题,甚至拖跨数据库。最终我们断定为开发的代码里应忘加了commit提交事务的操作,导致这一惨案的发生,可参考下面的重现操作。

前端应用JAVA Mybatis连接池一直不释放,积压过多的请求无法被处理,最终呈现给开发的现象是数据库又挂了。通俗来讲相当于在银行里办理业务,一个人办理不完,就得排队等待,越排越多,最终造成银行里人流混乱。


重现

MariaDB [test]

声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系 [邮箱地址] 删除

路过

雷人

握手

鲜花

鸡蛋

相关分类

返回顶部