达梦数据库阻塞死锁处理
一、 阻塞定义
阻塞通常指某个事务在等待其他事务释放锁资源,而不能继续进行,导致其被迫停滞。阻塞通常会导致性能问题和管理上的困难。例如,一个会话在等待另一个会话释放锁,期间它不能执行任何操作,这种情况就是典型的阻塞现象。如果这个等待的时间越长,它就越可能对数据库中的其他事务造成影响,从而影响到整个数据库系统的性能。此外,如果数据库管理员没有一套适合不同场景下的标准化阻塞处理流程,那么他们将难以对这些阻塞情况做出正确的判断和处理。
因为资源锁定而不能继续进行,需要等待锁被释放。这不仅影响到单个事务的执行,也可能拖慢整个数据库的性能。有效的阻塞管理和预防策略对于维持数据库性能和可靠性是非常关键的。
二、死锁与阻塞
数据库阻塞简介
在数据库操作中,当多个事务同时尝试访问同一资源而导致至少一个事务无法继续进行时,就会发生阻塞现象。阻塞可能导致数据库性能下降,影响整体的操作效率,甚至在严重的情况下会导致事务完全停滞。
解决数据库阻塞的策略
- 优化事务执行:调整事务执行的策略,确保操作效率,例如通过优化SQL语句或调整事务的执行顺序,减少资源竞争。
- 修复系统缺陷:识别并解决可能导致阻塞的系统缺陷或配置错误。持续监控系统性能,及时发现并解决这些问题可以显著降低阻塞发生的频率,确保数据库系统的稳定运行
数据库死锁简介
死锁的表现
死锁通常发生在多个数据库事务相互竞争资源时,每个事务持有部分资源并等待其他事务持有的资源释放,从而造成循环等待的局面。这种情况下,涉及的事务都无法继续执行,导致数据库操作的停滞。
如何解决死锁?
- 实时监控和自动解决:数据库系统通常内置死锁检测机制,能够自动识别并解决死锁问题。这些机制通过分析事务之间的等待图来检测死锁,当检测到死锁时,系统会自动中止一个或多个事务来解开死锁。
- 系统设计与预防:避免死锁的一个有效策略是在系统设计阶段就考虑到事务的资源访问顺序。确保所有事务按照一定的顺序访问资源可以减少死锁的发生。此外,定期审查和优化数据库的配置和代码,修复可能导致死锁的BUG,也是预防死锁的重要措施。
- 查询死锁历史记录的完整信息:
select * from V$DEADLOCK_HISTORY;
查询特定事务ID和会话ID相关的最重要SQL文本
select dh.trx_id, sh.sess_id, wm_concat(top_sql_text)
from V$DEADLOCK_HISTORY dh, V$SQL_HISTORY sh
where dh.trx_id = sh.trx_id and dh.sess_id = sh.sess_id
group by dh.trx_id, sh.sess_id;
为了追踪和分析导致数据库死锁的具体事务,可以查询V$DEADLOCK_HISTORY视图。这个视图提供了关于死锁事件的详细历史信息,使数据库管理员能够有效地识别和解决死锁问题。降 通过事务ID去sql日志中查找对应的事务确定完整的事务信息。根据完整的事务信息和死锁规则,去找其他影响的事务操作,确定业务功能设计从而优化处理逻辑消除或者降低死锁频率。
select timestampdiff(ss, LAST_RECV_TIME, sysdate), sf_get_session_sql(sess_id), *
from SYS."V$SESSIONS" where sess_id > sessid order by 1 desc;
如何解除阻塞?
阻塞可能是应用流程涉及提交慢导致,但是最终也会提交或者回滚,所以一般情况下也会自动消除。如果阻塞很长时间没有消除,在数据库层可以通过SP_CLOSE_SESSION(SESS_ID)来强制终止阻塞源头的会话使其回滚,来解除阻塞,但是这个需要用户确认,不能私自操作。
select * from V$SYSTEM_EVENT order by TIME_WAITED desc;
从系统时间中可以查看锁等待事件和地锁事件发生的次数和时间来评估是否存在死锁和阻塞。
CREATE TABLE TRX_WAIT
(
"STATTIME" TIMESTAMP,
"SS" INTEGER,
"WT" VARCHAR2(30),
"WT_SESS"STATTIME" TIMESTAMP,ID" BIGINT,
"WT_SQL_TEXT" VARCHAR(1000),
"WT_STATE" VARCHAR(10),
"WT_TRX_ID" BIGINT,
"WT_USER_NAME" VARCHAR(128),
"WT_CLNT_IP" VARCHAR(128),
"WT_APPNAME" VARCHAR(128),
"WT_LAST_SEND_TIME" DATETIME(6),
"FM" VARCHAR2(30),
"FM_SESS_ID" BIGINT,
"FM_SQL_TEXT" VARCHAR(1000),
"FM_STATE" VARCHAR(10),
"FM_TRX_ID" BIGINT,
"FM_USER_NAME" VARCHAR(128),
"FM_CLNT_IP" VARCHAR(128),
"FM_APPNAME" VARCHAR(128),
"F_LAST_SEND_TIME" DATETIME(6));
CREATE PROCEDURE GET_TRX_WAIT AS
BEGIN
INSERT INTO TRX_WAIT --创建辅助存储过程
SELECT SYSDATE STATTIME,DATEDIFF(SS,S1.LAST_SEND_TIME,SYSDATE) SS,'被阻塞的信息' WT,
S1.SESS_ID,WT_SESS_ID,S1.SQL_TEXT WT_SOL_TEXT,
S1.STATE WT_STATE,S1.TRX_ID WT_TRX_ID,
S1.USER_NAME WT_USER_NAME,S1.CLNT_IP WT CLNT IP,
S1.APPNAME WT_APPNAME,
S1.LAST_SEND_TIME WT_LAST_SEND_TIME,
'写起阻塞的信息' FM,
S2.SESS_ID FM_SESS_ID,
S2.SQL_TEXT FM_SOL_TEXT,
S2.STATE FM_STATE,
S2.TRX_ID FM_TRX_ID,
S2.USER_NAME FM_USER_NAME,
S2.CLNT_IP FM_CLNT_IP,
S2.APPNAME FM_APPNAME,
S2.LAST_SEND_TIME FM_LAST_SEND_TIME
FROM V$SESSIONS S1,V$SESSIONS S2,V$TRXWAIT W
WHERE S1.TRX_ID=W.ID
AND S2.TRX_ID=W.WAIT_FOR_ID:
COMMIT;
END;
—创建作业’“GETTRXWAIT”,每1分钟调度程序“GET_TRX_LOCK_NEW”
—创建作业进行定时收集阻塞数据
CALL SP_CREATE_JOB('GETTRXWAIT',1,0,'',0,0,'',0,''),
CALL SP_JOB_CONFIG START('GETTRXWAIT');
CALL SP_ADD_JOB_STEP('GETTRXWAIT, 'GETTRXWAIT', O, 'GETTRXWAIT',1, 2, 0, 0, NULL, O);
CALL SP_ADD_JOB_SCHEDULE('GETTRXWAIT','GETTRXWAIT,1,1,1.0,1,'00:00:00','23:59:59','2019-12-19 18:08:36',NULL,'');
CALL SP_JOB_CONFIG_COMMIT('GETTRXWAIT');
``
[https://eco.dameng.com](https://eco.dameng.com) 达梦社区