达梦数据库事务机制踩坑:默认不自动提交事务

达梦数据库事务机制踩坑:默认不自动提交事务

在 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

统一管理事务。

避免手动控制事务导致的问题。


相关推荐
小陈phd1 小时前
Qdrant 向量数据库从入门到实战:构建高效语义检索系统
数据库
xingyuzhisuan1 小时前
Redis 多级缓存落地聚合 API:重复请求降本 70% 实战数据
数据库·redis·缓存·ai
专注于大数据技术栈1 小时前
什么是Trino?大数据统一联邦查询引擎详解
大数据·数据库
数智化精益手记局2 小时前
拆解工程项目管理系统的核心功能:工程项目管理系统如何解决进度与成本难题
数据库·产品运营
weixin_523185322 小时前
Spring事务为什么会失效?常见场景与解决方案总结
java·数据库·spring
云絮.2 小时前
数据库约束
java·数据库·sql·mysql·oracle
cui_ruicheng10 小时前
MySQL(四):数据类型与字段设计
数据库·mysql
皮皮学姐分享-ppx10 小时前
政府绿色采购数据库(2015-2024.3)
大数据·网络·数据库·人工智能·制造
闪电悠米12 小时前
黑马点评-Redis 消息队列-03_stream_consumer_group
开发语言·数据库·redis·分布式·缓存·junit·lua