如何迅速杀掉数据库里inactive的会话

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何迅速杀掉数据库里inactive的会话相关的知识,希望对你有一定的参考价值。

在Oracle数据库中,经常会产生一些inactive的会话,但是仍然连接到数据库,一般情况下,我们可以使用alter system kill session 'sid,serial#'; 来强制杀掉他,但是如果我们有大量的这种进程,要手动一个一个去杀掉,是比较麻烦的。
下面有个方法,可以迅速的杀掉这些进程。

SELECT 'ALTER SYSTEM DISCONNECT SESSION ''' || B.SID || ',' || B.SERIAL# ||
'''IMMEDIATE;'
FROM V$LOCKED_OBJECT A, V$SESSION B, DBA_OBJECTS C

WHERE B.SID = A.SESSION_ID
参考技术A 重点是肯定有资源没有释放,先确定是不是connction,statement,preparedstatement,resultset等资源没有释放(一般connection可能性不大,大家都挺注意,关键是后面几个),如果不是那只能用jconsole或者jprofile分析了 参考技术B 重点是肯定有资源没有释放,先确定是不是connction,statement,preparedstatement,resultset等资源没有释放(一般connection可能性不大,大家都挺注意,关键是后面几个),如果不是那只能用jconsole或者jprofile分析了

堵塞MySQL的会话是如何被快速杀掉的

前言

查找Innodb里面的锁,可以通过information_schema库下相关事务表和锁相关信息表来查到,在8.0的环境下,通过sys库下的锁相关表查询。一键获取Mysql笔记

information_schema.innodb_trx
存储了当前正在执行的事务信息

information_schema.innodb_locks
记录了锁信息如果一个事务想要获取到某个锁但未获取到,则记录该锁信息如果一个事务获取到了某个锁,但是这个锁阻塞了别的事务,则记录该锁信息但是无法通过该表查询到谁被阻塞,谁持有未释放。

information_schema.innodb_lock_waits
表明每个阻塞的事务是因为获取不到哪个事务持有的锁而被阻塞

information_schema.processlist
连接信息表

performance_schema.events_statements_current
记录当前执行的sql

performance_schema.events_statements_history
记录执行过的sql

sys.innodb_lock_waits 表

locked_table : 哪张表出现的等待

waiting_trx_id: 等待的事务(与上个视图trx_id 对应)

waiting_pid : 等待的连接号(与上个视图trx_mysql_thread_id或processlist_id)

blocking_trx_id : 锁源的事务ID

blocking_pid : 锁源的连接号

单一的锁快速查找方法

通过information_schema库下的锁信息表查询

整个流程如下:

(1)首先查询是否有锁,根据锁查到被锁的trx_id

(2)根据被锁的trx_id可以查到锁源的trx_id

(3)根据锁源的trx_id查到trx_mysql_thread_id(即processlist_id)

(4)再根据trx_mysql_thread_id查到thread_id

(5)最后,用thread_id查找到锁源的sql

但是这种方法在mysql8.0已经被移除,介绍另外一张表

通过sys库下的锁信息表查询

注意: MySQL8.0删除了information_schema.innodb_locks,添加了performance_schema.data_locks,可以通过performance_schema.data_locks查看事务的锁情况,和MySQL5.7及之前不同,performance_schema.data_locks不但可以看到阻塞该事务的锁,还可以看到该事务所持有的锁,也就是说即使事务并未被阻塞,依然可以看到事务所持有的锁(不过,正如文中最后一段所说,performance_schema.data_locks并不总是能看到全部的锁)。表名的变化其实还反映了8.0的performance_schema.data_locks更为通用了,即使你使用InnoDB之外的存储引擎,你依然可以从performance_schema.data_locks看到事务的锁情况。

因此第一种方法并不适用于8.0

通过sys库查询流程如下和第一种方式的原理其实是一样的

锁源的事务trx_id -->pnformaction_schema.processlist表的连接id–>performance_schema.threads表的thread_id–>performance_schema.events_statements_current 或performance_schema.events_statements_history查看sql

需要注意的是如下的三个id其实是同一个id,我这里把他们同称为连接ID,因为是由CONNECTION_ID()函数返回的

information_schema.innodb_trx(trx_mysql_thread_id)

information_schema.processlist(id)

sys.innodb_lock_waits(waiting_pid,blocking_pid)           

复杂的锁环境怎么快速查找肇事者

innodb_lock_waits

表明每个阻塞的事务是因为获取不到哪个事务持有的锁而被阻塞

requesting_trx_id:–获取不到锁而被阻塞的事务id(等待方)

requested_lock_id:-- 请求锁ID ,事务所等待的锁定的 ID。可以和 INNODB_LOCKS 表 JOIN。

blocking_trx_id: --获取到别的事务需要的锁而阻塞其事务的事务id(当前持有方,待释放)

blocking_lock_id: --这一事务的锁的 ID,该事务阻塞了另一事务的运行。可以和 INNODB_LOCKS 表 JOIN。

sys.innodb_lock_waits 表

locked_table : 哪张表出现的等待

waiting_trx_id: 等待的事务(与上个视图trx_id 对应)

waiting_pid : 等待的连接号(与上个视图trx_mysql_thread_id或processlist_id)

blocking_trx_id : 锁源的事务ID

blocking_pid : 锁源的连接号

sys.innodb_lock_waits的来源

SELECT r.trx_wait_started AS wait_started,
       TIMEDIFF(NOW(), r.trx_wait_started) AS wait_age,
       TIMESTAMPDIFF(SECOND, r.trx_wait_started, NOW()) AS wait_age_secs,
       rl.lock_table AS locked_table,
       rl.lock_index AS locked_index,
       rl.lock_type AS locked_type,
       r.trx_id AS waiting_trx_id,
       r.trx_started as waiting_trx_started,
       TIMEDIFF(NOW(), r.trx_started) AS waiting_trx_age,
       r.trx_rows_locked AS waiting_trx_rows_locked,
       r.trx_rows_modified AS waiting_trx_rows_modified,
       r.trx_mysql_thread_id AS waiting_pid,
       sys.format_statement(r.trx_query) AS waiting_query,
       rl.lock_id AS waiting_lock_id,
       rl.lock_mode AS waiting_lock_mode,
       b.trx_id AS blocking_trx_id,
       b.trx_mysql_thread_id AS blocking_pid,
       sys.format_statement(b.trx_query) AS blocking_query,
       bl.lock_id AS blocking_lock_id,
       bl.lock_mode AS blocking_lock_mode,
       b.trx_started AS blocking_trx_started,
       TIMEDIFF(NOW(), b.trx_started) AS blocking_trx_age,
       b.trx_rows_locked AS blocking_trx_rows_locked,
       b.trx_rows_modified AS blocking_trx_rows_modified,
       CONCAT('KILL QUERY ', b.trx_mysql_thread_id) AS sql_kill_blocking_query,
       CONCAT('KILL ', b.trx_mysql_thread_id) AS sql_kill_blocking_connection
  FROM information_schema.innodb_lock_waits w
       INNER JOIN information_schema.innodb_trx b    ON b.trx_id = w.blocking_trx_id
       INNER JOIN information_schema.innodb_trx r    ON r.trx_id = w.requesting_trx_id
       INNER JOIN information_schema.innodb_locks bl ON bl.lock_id = w.blocking_lock_id
       INNER JOIN information_schema.innodb_locks rl ON rl.lock_id = w.requested_lock_id
 ORDER BY

可以发现information_schema.innodb_lock_waits的blocking_trx_id中出现次数最多的事务ID很可能就是堵塞的源头,而sys.innodb_lock_waits中的信息正是完全来自information_schema.innodb_lock_waits和其他两个表的join

(1)执行语句找出堵塞最多的session

select trim(LEADING 'KILL ' from sql_kill_blocking_connection),count(*)
from sys.innodb_lock_waits  
group by trim(LEADING 'KILL ' from sql_kill_blocking_connection) order by count(*) desc;

(2)排名第一个的说明堵塞的会话越多。

找到排名第一的process id 当前的事务信息

观察其事务状态和可能执行的语句或者上一条语句判断是否可以杀掉。

select trx_id,trx_operation_state,trx_mysql_thread_id prs_id,now(),trx_started,
to_seconds(now())-to_seconds(trx_started) trx_es_time,
user,db,host,state,Time,info current_sql,PROCESSLIST_INFO last_sql
from information_schema.innodb_trx t1,information_schema.processlist t2,performance_schema.threads  t3
where t1.trx_mysql_thread_id=t2.id 
and   t1.trx_mysql_thread_id=t3.PROCESSLIST_ID
and   t1.trx_mysql_thread_id!=connection_id()
and   t2.id=;

最后

整理了一份Mysql笔记已整理成PDF文档,共有578页,可免费分享。

👇🏻 添加 博主 获取更多资料👇🏻

以上是关于如何迅速杀掉数据库里inactive的会话的主要内容,如果未能解决你的问题,请参考以下文章

教你如何迅速秒杀掉:99%的海量数据处理面试题(转)

教你如何迅速秒杀掉:99%的海量数据处理面试题

教你如何迅速秒杀掉:99%的海量数据处理面试题

ORACLE定期清理INACTIVE会话

如何杀掉(kill)Oracle中的会话(Session)

ORACLE定期清理INACTIVE会话