MySQL Sleep 进程 导致会话堵塞问题

tech2022-07-31  155

一、背景 我们在生产环境中,经常会遇到一些,没有sql语句,状态为sleep的进程阻塞大量会话的问题。对此,我们进行了测试分析。下面把详细的分析过程分享如下:

二、测试 1.准备 mysql> desc jyf_test_tbs; ±------±------------±-----±----±--------±---------------+ | Field | Type | Null | Key | Default | Extra | ±------±------------±-----±----±--------±---------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | name | varchar(60) | YES | | NULL | | ±------±------------±-----±----±--------±---------------+ 2 rows in set (0.01 sec)

mysql> select * from jyf_test_tbs; ±—±---------+ | id | name | ±—±---------+ | 1 | jinyoufu | | 2 | xu | ±—±---------+ 2 rows in set (0.01 sec)

建表。

2.分析 在会话一:开始一个事务

mysql> mysql> begin; Query OK, 0 rows affected (0.00 sec)

mysql> select * from jyf_test_tbs for update; ±—±---------+ | id | name | ±—±---------+ | 1 | jinyoufu | | 2 | xu | ±—±---------+ 2 rows in set (0.00 sec)

mysql> show processlist; ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ | Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined | ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ | 110 | root | localhost | NULL | Sleep | 29 | | NULL | 0 | 0 | | 112 | root | localhost | jyfdb | Query | 0 | starting | show processlist | 0 | 0 | ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ 2 rows in set (0.01 sec)

会话一自己查看的是:Query 状态

会话二:显示会话一已经是Sleep状态

±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ | Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined | ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ | 110 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 | | 112 | root | localhost | jyfdb | Sleep | 208 | | NULL | 0 | 0 | ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+

*************************** 1. row *************************** ifnull(trx_id, ‘null’): 164427 ifnull(trx_state,‘null’): RUNNING ifnull(trx_started,‘null’): 2020-09-02 20:23:00 ifnull(trx_wait_started,‘null’): null ifnull(trx_weight,‘null’): 2 ifnull(trx_mysql_thread_id,‘null’): 112 ifnull(trx_query,‘null’): null ifnull(trx_operation_state,‘null’): null ifnull(TRX_TABLES_IN_USE,‘null’): 0 ifnull(trx_rows_locked,‘null’): 3 ifnull(trx_rows_modified,‘null’): 0 ifnull(trx_tables_locked,‘null’): 1 1 row in set (0.00 sec)

我们进一步分析,从innodb 可以看出:

—TRANSACTION 164427, ACTIVE 599 sec 2 lock struct(s), heap size 1136, 3 row lock(s) MySQL thread id 112, OS thread handle 140413782394624, query id 1615465 localhost root

查看事务的情况:从这里我们可以看出处于sleep的事务164427 实际上还是在运行中,且锁定了3条Records。

事务一直不提交,就会一直堵塞对这些Records操作的会话。

在会话一:提交事务

mysql> commit; Query OK, 0 rows affected (0.00 sec)

锁资源释放。事务结束。

在会话一:直接中断会话连接

±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ | Id | User | Host | db | Command | Time | State | Info | Rows_sent | Rows_examined | ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+ | 110 | root | localhost | NULL | Query | 0 | starting | show processlist | 0 | 0 | | 112 | root | localhost | jyfdb | Sleep | 208 | | NULL | 0 | 0 | ±----±-----±----------±------±--------±-----±---------±-----------------±----------±--------------+

*************************** 1. row *************************** ifnull(trx_id, ‘null’): 164427 ifnull(trx_state,‘null’): RUNNING ifnull(trx_started,‘null’): 2020-09-02 20:23:00 ifnull(trx_wait_started,‘null’): null ifnull(trx_weight,‘null’): 2 ifnull(trx_mysql_thread_id,‘null’): 112 ifnull(trx_query,‘null’): null ifnull(trx_operation_state,‘null’): null ifnull(TRX_TABLES_IN_USE,‘null’): 0 ifnull(trx_rows_locked,‘null’): 3 ifnull(trx_rows_modified,‘null’): 0 ifnull(trx_tables_locked,‘null’): 1 1 row in set (0.00 sec)

事务可能依然存在会形成僵尸进程,等待锁超时。(数据库也可能会回滚事务,具体要根据情况分析)

三、分析结论 针对以上的测试分析,我们可以发现:如果事务没有提交或者出现异常中断导致没有提交或者回滚,会话就会变成sleep进程,依然会锁定资源。

感觉是一个正常的sleep的进程,其实锁定了很多Records,且抓不到什么SQL语句。但是,堵塞了正常的业务。高并发下,会造成数据库无法响应的情况。

快速处理:定位问题事务,kill掉堵塞的事务的会话。 SQL> kill thread_id;

四、整改建议 1.设置合理的锁超时机制。

2.程序代码中,务必保证每个事务都及时的commit。

最新回复(0)