在数据库管理系统中,死锁与阻塞是一个常见的问题,特别是在高并发环境下。本文将探讨达梦数据库中的死锁与阻塞的问题,分析其成因、检测方法以及解决方案
1.什么是死锁
2.什么是阻塞
达梦数据库提供了多种死锁检测机制,包括:
相关动态视图
视图 描述
V$SESSIONS 显示会话的具体信息
V$TRX 显示所有活动事务的信息
V$TRXWAIT 显示事务等待信息
V$TRX_VIEW 显示活动事务视图信息
V$LOCK 显示当前系统中锁的状态
V$DEADLOCK_HISTORY 显示死锁的历史信息
相关参数
参数 描述
DDL_WAIT_TIME DDL操作的锁超时时间
BLDR_WAIT_TIME 批量装载时锁超时时间
死锁不用人工干涉,数据库系统自动识别并解除。但是死锁是非正常情况,需要找到死锁原因后,从应用逻辑层解决。
阻塞 可能是应用流程涉及提交慢导致,但是最终也会提交或者回滚,所以一般情况下也会自动消除。如果阻塞很长时间没有消除,在数据库层可以通过 SP_CLOSE_SESSION(SESSID);来强制终阻塞源头的会话使其回滚,来解除阻塞,但是这个需要用户确认,不能私自操作。
1.从系统时间中可以查看锁等待事件和地锁事件发生的次数和时间来评估是否存在死锁和阻塞
查询语句:SELECT * FROM V$SYSTEM_EVENT ORDER BY TIME_WAITED DESC;
2.可以通过辅助表跟踪阻塞
STEP1:创建辅助记录表:
CREATE TABLE TRX_WAIT(
"STATTIME" TIMESTAMP,
"SS" INTEGER,
"WT" VARCHAR2(30),
"WT_SESS_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),
"FM LAST SEND TIME"DATETIME(6)
);
STEP2:创建辅助存储过程GET_TX_WAIT
CREATE PROCEDURE GET_TX_WAIT AS
BEGIN
INSERT INTO TRX_WAIT
SELECT SYSDATE AS STATTIME,
DATEDIFF(SS,S1.LAST_SEND_TIME,SYSDATE) AS SS,
'被阻塞的信息' AS WT,
S1.SESS_ID AS WT_SESS_ID,
S1.SQL_TEXT AS WT_SQL_TEXT,
S1.STATE AS WT_STATE,
S1.TRX_ID AS WT_TRX_ID,
S1.USER_NAME AS WT_USER_NAME,
S1.CLNT_IP AS WT_CLNT_IP,
S1.APPNAME AS WT_APPNAME,
S1.LAST_SEND_TIME AS WT_LAST_SEND_TIME,
'引起阻塞的信息' AS FM,
S2.SESS_ID AS FM_SESS_ID,
S2.SQL_TEXT AS FM_SQL_TEXT,
S2.STATE AS FM_STATE,
S2.TRX_ID AS FM_TRX_ID,
S2.USER_NAME AS FM_USER_NAME,
S2.CLNT_IP AS FM_CLNT_IP,
S2.APPNAME AS FM_APPNAME,
S2.LAST_SEND_TIME AS 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;
STEP3:创建作业定时收集阻塞数据
1.创建测试表并插入数据
-- 创建测试表
CREATE TABLE test (
id INT PRIMARY KEY,
balance DECIMAL(10,2)
);
-- 插入测试数据
INSERT INTO test VALUES (1, 1000.00);
INSERT INTO test VALUES (2, 2000.00);
Commit;
2.模拟死锁场景
开两个会话,依次执行两个会话的第一条修改语句,再依次执行第二条语句
会话1:
UPDATE test SET balance = balance - 100 WHERE id = 1; -- 锁定 id=1 的行
UPDATE test SET balance = balance + 100 WHERE id = 2; -- 尝试获取 id=2 的锁(被 Session 2 占用)
-- 此时 Session 1 会等待 Session 2 释放锁
会话2:
UPDATE test SET balance = balance + 100 WHERE id = 2; -- 锁定 id=2 的行
UPDATE test SET balance = balance - 100 WHERE id = 1; -- 尝试获取 id=1 的锁(被 Session 1 占用)
-- 此时达梦检测到死锁,自动终止其中一个事务
3.死锁解决
达梦自动检测出现死锁情况,并终止会话2中的第二条语句执行
select * from v$lock where blocked=1; – 查看死锁情况
select * from V$SESSIONS; --显示会话具体信息
执行call sp_close_session(‘140468046420600’);并提交
再次执行select * from v$lock where blocked=1;确认死锁已被杀
文章
阅读量
获赞