上一篇
凌晨2点,你的手机突然响起——数据库监控告警!某个核心业务表被锁死,前端订单提交全部卡死,你连上服务器一看:锁表的会话是个陈年遗留任务,kill sid
居然返回“操作无法完成”,后台进程像焊死在数据库里一样纹丝不动…
别慌!这种“僵尸会话”是DBA的经典考题,今天我们就拆解这套组合拳,从问题定位到暴力清除,一步步教你搞定顽固锁表。
快速定位锁表会话
-- Oracle查锁表(含SID和序列号) SELECT l.session_id sid, s.serial#, s.username, s.machine, l.oracle_username, l.locked_mode, o.object_name, s.logon_time FROM v$locked_object l, dba_objects o, v$session s WHERE l.object_id = o.object_id AND l.session_id = s.sid ORDER BY s.logon_time; -- MySQL版本(8.0+) SELECT trx_id, trx_mysql_thread_id, trx_query, trx_state, trx_started FROM information_schema.innodb_trx WHERE trx_state = 'LOCK WAIT';
关键字段解读:
sid
:会话ID(杀进程用) serial#
:Oracle必须配合使用的序列号 locked_mode
:锁模式(3=排他锁,最危险) trx_mysql_thread_id
:MySQL线程ID 检查会话详情
-- Oracle查看会话完整信息 SELECT s.sid, s.serial#, s.status, s.server, s.osuser, s.program, s.module, s.action, s.blocking_session FROM v$session s WHERE s.sid = [锁表SID];
Oracle标准操作
-- 必须带上serial#才能生效! ALTER SYSTEM KILL SESSION 'sid,serial#' IMMEDIATE;
MySQL标准操作
KILL [trx_mysql_thread_id];
# 先找到Oracle会话的OS进程ID SELECT p.spid, s.sid, s.serial#, s.username FROM v$session s, v$process p WHERE s.paddr = p.addr AND s.sid = [锁表SID]; # 直接kill -9(谨慎!) kill -9 [spid]
💡 注意:如果是在RAC环境中,需确认进程所在节点
-- 给会话发送终止信号并设置超时 ALTER SYSTEM DISCONNECT SESSION 'sid,serial#' POST_TRANSACTION; ALTER SYSTEM DISCONNECT SESSION 'sid,serial#' IMMEDIATE;
# Oracle重启单实例 sqlplus / as sysdba shutdown abort; startup; # MySQL服务重启 systemctl restart mysqld
⚠️ 风险提示:生产环境需评估业务影响,优先在维护窗口操作
如果锁表的是InnoDB长事务:
-- 查看当前长事务(MySQL 5.7+) SELECT * FROM performance_schema.events_transactions_current WHERE TIMESTAMPDIFF(SECOND, START_TIME, NOW()) > 60; -- 强制回滚事务(需super权限) KILL QUERY [thread_id];
-- 创建临时资源计划限制会话 BEGIN DBMS_RESOURCE_MANAGER.CREATE_PENDING_AREA(); DBMS_RESOURCE_MANAGER.CREATE_CONSUMER_GROUP('EMERGENCY_GROUP'); DBMS_RESOURCE_MANAGER.SET_CONSUMER_GROUP_MAPPING( attribute => 'SESSION_ID', value => '[锁表SID]', consumer_group => 'EMERGENCY_GROUP'); DBMS_RESOURCE_MANAGER.SUBMIT_PENDING_AREA(); END; / -- 限制该组CPU为0% UPDATE plan_directives SET mgmt_p1 = 0 WHERE plan = 'DEFAULT_PLAN' AND group_or_subplan = 'EMERGENCY_GROUP';
如果锁表的是DDL操作:
-- 将表空间设为只读强制会话中断 ALTER TABLESPACE [表空间名] READ ONLY;
事务最小化
SELECT FOR UPDATE
后长时间不提交 监控常态化
-- Oracle创建锁表预警 CREATE OR REPLACE TRIGGER lock_alert AFTER SERVERERROR ON DATABASE WHEN (ORA_IS_SERVERERROR(60)) -- ORA-00060死锁错误 BEGIN utl_mail.send('[email protected]', '紧急锁表告警', '检测到数据库死锁!'); END;
会话生命周期管理
ALTER SESSION SET idle_timeout=3600
处理杀不掉的SID就像给数据库做“外科手术”,关键要稳准狠:
kill -9
或重启服务 所有kill操作都是止血手段,根治问题要靠合理的架构设计和监控,下次再遇到僵尸会话,希望你能淡定地掏出这份指南~
本文由 焦霞 于2025-08-03发表在【云服务器提供商】,文中图片由(焦霞)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/523876.html
发表评论