达梦数据库采用 MVCC(多版本并发控制)+ 封锁(Lock)混合机制,通过维护数据的多个版本实现读写不互相阻塞。核心原理:
-- 查看当前隔离等级
-- 一般设置为读已提交(1)和串行化(3)
SELECT PARA_VALUE
FROM V$DM_INI
WHERE PARA_NAME = 'ISOLATION_LEVEL';
--全局修改,需要重启数据库
SP_SET_PARA_VALUE(2, 'ISOLATION_LEVEL', 1);
--只修改下一个事务
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
测试环境
-- 创建测试表和数据
DROP TABLE IF EXISTS mvcc_test;
CREATE TABLE mvcc_test (
id INT PRIMARY KEY,
value INT,
name VARCHAR(50)
);
-- 插入初始数据
INSERT INTO mvcc_test VALUES (1, 100, '初始值');
INSERT INTO mvcc_test VALUES (2, 200, '测试数据');
COMMIT;
-- 确认数据
SELECT * FROM mvcc_test;
-- 结果:
-- ID | VALUE | NAME
-- 1 | 100 | 初始值
-- 2 | 200 | 测试数据
测试一:读未提交
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
-- 事务一
UPDATE MVCC_TEST SET VALUE = 1000, NAME='初始值被修改' WHERE ID = 1;
-- 事务二
select * from MVCC_TEST
事务一执行
事务一未提交,事务二可以查到
测试二:读提交
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 事务一
UPDATE MVCC_TEST SET VALUE = 1000, NAME='初始值被修改' WHERE ID = 1;
-- 事务二
select * from MVCC_TEST
-- 事务一
commit
-- 事务二
select * from MVCC_TEST
事务一未提交,事务二没有查到修改后的数据
事务一提交后,事务二可以查到修改后的数据
另外,开串行化后,事务一提交了,事务二也看不到修改后的数据。
幻读
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
-- 事务一
SELECT COUNT(*) FROM MVCC_TEST WHERE ID > 0;
-- 事务二
INSERT INTO MVCC_TEST VALUES (3, 300, '新数据');
commit
-- 事务一
SELECT COUNT(*) FROM MVCC_TEST WHERE ID > 0;
-- 然后切换成串行化再执行一遍
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
读已提交,事务二未插入数据
插入数据后
串行化,未插入数据
插入数据后
MVCC 相关系统视图速查
| 视图名 | 用途 |
|---|---|
V$TRX |
显示所有活动事务的信息 |
V$TRX_VIEW |
显示活动事务的视图信息 |
V$TRXWAIT |
显示事务等待的信息 |
V$LOCK |
查看 MVCC 历史版本信息 |
文章
阅读量
获赞
