达梦数据库事务机制踩坑:默认不自动提交事务
在 MySQL、PostgreSQL 等数据库开发中,很多开发者已经习惯了:
text执行SQL ↓ 自动提交但在使用达梦数据库(DM Database)时,经常会遇到这样的问题:
- SQL执行成功却查不到数据
- 程序退出后数据丢失
- Navicat执行Insert没有生效
- JDBC操作后数据库没有更新
很多时候并不是 SQL 有问题,而是:
text事务没有提交本文结合实际开发经验,总结达梦数据库事务机制及常见踩坑场景。
目录
- 达梦数据库简介
- 什么是事务
- 自动提交与手动提交
- 达梦数据库事务特点
- 常见踩坑场景
- JDBC中的事务控制
- Spring事务与达梦数据库
- 如何查看事务状态
- 常见问题排查
- 面试高频问题
- 总结
一、达梦数据库简介
达梦数据库(DM Database)是国产关系型数据库的重要代表之一。
常见应用领域:
text
政府项目
金融系统
国企项目
军工行业
信创项目
官方网站:
text
达梦数据库(DM)
目前主流版本:
text
DM8
SQL语法与Oracle较为接近。
例如:
sql
SELECT *
FROM USER_INFO;
二、什么是事务
事务(Transaction):
一组操作要么全部成功,要么全部失败。
例如:
sql
UPDATE ACCOUNT
SET MONEY = MONEY - 100
WHERE ID = 1;
sql
UPDATE ACCOUNT
SET MONEY = MONEY + 100
WHERE ID = 2;
如果第一条执行成功:
第二条失败:
text
账户金额异常
因此需要事务:
text
全部成功
或
全部回滚
三、自动提交与手动提交
数据库事务有两种模式:
自动提交(Auto Commit)
执行:
sql
INSERT ...
立即生效:
text
自动COMMIT
例如:
text
MySQL
默认:
text
autocommit = ON
执行:
sql
INSERT INTO USER_INFO
VALUES(1,'Tom');
立即写入数据库。
手动提交(Manual Commit)
执行:
sql
INSERT ...
不会立刻生效。
需要:
sql
COMMIT;
才真正提交。
例如:
sql
INSERT INTO USER_INFO
VALUES(1,'Tom');
然后:
sql
COMMIT;
数据才持久化。
四、达梦数据库事务特点
很多开发者第一次接触达梦时会踩坑。
因为:
text
达梦更强调事务控制
在部分客户端工具和配置环境下:
text
不会自动提交事务
例如:
sql
INSERT
UPDATE
DELETE
执行后:
text
数据可能还在当前事务中
此时:
sql
SELECT
当前连接能查到。
但是:
text
其他连接查不到
因为:
text
事务尚未提交
五、经典踩坑案例
场景一:插入成功却查不到
执行:
sql
INSERT INTO USER_INFO
(ID,NAME)
VALUES
(1,'Tom');
返回:
text
执行成功
当前连接:
sql
SELECT *
FROM USER_INFO;
能看到数据。
重新打开窗口:
sql
SELECT *
FROM USER_INFO;
发现:
text
查不到
原因:
text
未提交事务
解决:
sql
COMMIT;
六、场景二:程序退出后数据消失
JDBC代码:
java
connection.executeUpdate(sql);
程序结束。
重新查询:
text
数据不存在
原因:
java
未调用commit()
正确写法:
java
connection.commit();
七、场景三:Navicat执行SQL不生效
执行:
sql
UPDATE USER_INFO
SET NAME='Jerry'
WHERE ID=1;
提示:
text
执行成功
重新查询:
text
没有变化
检查:
text
自动提交关闭
解决:
sql
COMMIT;
或者:
text
开启自动提交
八、JDBC事务控制
默认写法:
java
Connection conn =
dataSource.getConnection();
关闭自动提交:
java
conn.setAutoCommit(false);
执行SQL:
java
statement.executeUpdate(sql);
提交:
java
conn.commit();
回滚:
java
conn.rollback();
完整示例:
java
try {
conn.setAutoCommit(false);
statement.executeUpdate(sql1);
statement.executeUpdate(sql2);
conn.commit();
} catch (Exception e) {
conn.rollback();
}
九、Spring事务与达梦数据库
使用Spring后:
java
@Transactional
通常不需要手动:
java
commit()
Spring会自动处理:
text
开启事务
↓
执行SQL
↓
提交事务
例如:
java
@Transactional
public void save() {
mapper.insert(user);
}
执行成功:
text
自动提交
发生异常:
text
自动回滚
十、如何查看事务状态
查看当前事务:
sql
SELECT *
FROM V$TRX;
查看会话:
sql
SELECT *
FROM V$SESSIONS;
查看锁:
sql
SELECT *
FROM V$LOCK;
常用于排查:
text
事务未提交
事务阻塞
死锁问题
十一、事务未提交带来的问题
数据不可见
例如:
text
当前连接能查到
其他连接查不到
长事务
事务长期不提交:
text
占用资源
导致:
text
性能下降
锁无法释放
例如:
sql
UPDATE USER_INFO
后不提交。
其他事务:
sql
UPDATE USER_INFO
可能被阻塞。
最终:
text
系统响应变慢
十二、事务相关SQL
提交事务:
sql
COMMIT;
回滚事务:
sql
ROLLBACK;
设置自动提交:
sql
SET AUTOCOMMIT ON;
关闭自动提交:
sql
SET AUTOCOMMIT OFF;
实际使用时应根据客户端工具确认配置。
十三、开发中的最佳实践
1、统一使用Spring事务
推荐:
java
@Transactional(
rollbackFor = Exception.class
)
避免:
java
手动commit()
和:
java
手动rollback()
大量散落在业务代码中。
2、事务尽量短
不要:
java
@Transactional
public void save() {
Thread.sleep(30000);
}
避免:
text
长事务
3、及时提交事务
完成业务后:
sql
COMMIT;
避免:
text
锁表
阻塞
资源浪费
4、排查工具配置
重点检查:
text
Navicat
DBeaver
DataGrip
达梦管理工具
是否开启:
text
自动提交
十四、面试高频问题
面试题1
事务是什么?
答案:
text
一组操作要么全部成功
要么全部失败
面试题2
COMMIT作用是什么?
答案:
text
提交事务
永久保存数据
面试题3
ROLLBACK作用是什么?
答案:
text
回滚事务
撤销未提交操作
面试题4
为什么执行成功却查不到数据?
答案:
text
事务未提交
面试题5
Spring事务需要手动commit吗?
答案:
text
通常不需要
Spring自动管理
面试题6
事务长期不提交会导致什么问题?
答案:
text
锁占用
阻塞
性能下降
长事务问题
十五、实际项目经验总结
在达梦项目中最常见的问题:
text
SQL执行成功
数据却没有落库
排查步骤:
第一步
确认:
sql
COMMIT;
是否执行。
第二步
确认:
java
setAutoCommit(false)
是否开启。
第三步
确认:
java
@Transactional
是否生效。
第四步
检查:
sql
V$TRX
查看事务状态。
总结
达梦数据库开发过程中需要特别关注事务控制。
牢记:
text
SQL执行成功
≠
事务提交成功
常见问题本质都是:
text
事务没有提交
导致。
核心事务命令:
提交:
sql
COMMIT;
回滚:
sql
ROLLBACK;
实际项目推荐:
java
@Transactional
统一管理事务。
避免手动控制事务导致的问题。