数据同学反馈凌晨1-2点会出现连接系统MySQL数据库等待锁超时
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
InnoDB事务等待一个行级锁的时间最长时间默认值是50秒(单位是秒),超过这个时间就会放弃。一个事务A试图访问一行数据,但是这行数据正在被另一个innodb事务B锁定,此时事务A就会等待事务B释放锁,等待超过innodb_lock_wait_timeout设置的值就会报错。
最直接的解决方案,就是调整innodb_lock_wait_timeout超时参数(治标不治本):
第一种在MySQL的配置文件中加入,然后重启MySQL
innodb_lock_wait_timeout = 500
第二种直接执行如下命令
set global innodb_lock_wait_timeout=500;
1、根据Druid的监控查看慢SQL,发现超过100S的慢SQL:
SELECT
*
FROM
( SELECT * FROM rule_result WHERE org_id = '67303' AND state = 0 AND exec_date = '2022-12-25' ) result
WHERE
exec_result = 0
ORDER BY
person_idcard ASC
LIMIT 0,
10
explain解释执行,选择的索引是Order By后的idcard索引。子查询就没有走索引,所以出现了慢SQL:
优化后:
SELECT
person_name AS NAME,
person_idcard AS idcard,
person_phone AS phone,
org_id AS companyId,
org_name AS companyName,
dept_name AS deptName,
rule_name AS ruleName,
exec_date AS execDate,
exec_result AS execResult,
org_id AS orgId,
window_value AS windowValue,
type_name AS peopleTypeName,
person_idcard_code AS idcardCode,
window_start AS windowStart
FROM
( SELECT * FROM kp_rule_result WHERE org_id = '67303' AND state = 0 AND exec_date = '2023-01-04' ) result
ORDER BY
person_idcard ASC
explain解释执行,选择子查询的索引,效率更高,只需要1点几秒(直接去掉身份证排序也行):
2、慢SQL排查完成后,两天内是好了,不过后来数据同学发现要先删表再写入中间结果,数据量量大时间太慢导致他的其他事务等待锁中断了。
2.1、什么是MySQL慢查询呢?
其实就是查询的SQL语句耗费较长的时间。正常情况下,MySQL是不会自动开启慢查询的,且如果开启的话默认阈值是10秒
具体耗费多久算慢查询呢?这其实因人而异,有些公司慢查询的阈值是100ms,有些的阈值可能是500ms,即查询的时间超过这个阈值即视为慢查询。
# slow_query_log 表示是否开启
mysql> show global variables like '%slow_query_log%';
+---------------------+--------------------------------------+
| Variable_name | Value |
+---------------------+--------------------------------------+
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/0bd9099fc77f-slow.log |
+---------------------+--------------------------------------+
# long_query_time 表示慢查询的阈值,默认10秒
show global variables like '%long_query_time%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
2.2、MySQL慢查询危害
1、当表是Myisam表,对表有慢查询,不阻塞Select,对该表的其他DML、DDL操作都会被阻塞。
2、当表是Innodb表,当表上有慢查询,不阻塞Select 和DML,其他的DDL操作都会被阻塞,比如出现waiting for table metadata lock。
为啥会造成DDL操作阻塞?
众所周知,InnoDB引擎默认加的是行锁,但锁其实都是加在索引上的,如果筛选条件没有建立索引,会降级到表锁。而慢查询有一大部分原因都是因为没加索引导致的,所以慢查询时间过长,就会导致表锁的时间也很长,如果这时候执行DDL就会造成阻塞。
综上,当数据库中存在慢查询时,是比较危险的,当执行备份、create index、alter table 、flush table 等操作时就会造成数据库的等待。
2.3、如何避免慢查询
1、对查询SQL,进行压测,该加索引就加索引;
2、如果有索引,进行explain执行计划分析避免索引失效的情况;
参考链接:
Mysql 异常:MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction - 简书