河池市网站建设_网站建设公司_交互流畅度_seo优化
2025/12/24 14:17:22 网站建设 项目流程

什么,怎么用的就是数据库事务

数据库事务(Transaction)是一组不可分割的 SQL 执行单元,要么全部执行成功(提交),要么全部执行失败(回滚),本质是 “原子性的操作集合”,用于保证数据一致性。

事务的核心是保证数据一致性,通过 ACID 特性实现;基本用法:开启事务 → 执行SQL → 提交/回滚;实际开发中,优先用框架的声明式事务(如 Spring 的@Transactional),减少手动编码;不同数据库的事务隔离级别是关键差异,需结合业务场景选择。

目录

1.事务的核心特性(ACID)

2.事务的使用场景

3.事务的基本操作(SQL 层面)

3.1 开启事务

3.2 执行 SQL(核心业务逻辑)

3.3 提交事务(成功时)

3.4 回滚事务(失败时)

3.5 保存点(进阶:部分回滚)

4.不同数据库的事务差异(重点)

5.实际开发中的使用(以 Java 为例)

5.1 原生 JDBC 实现事务

5.2 框架层面(Spring Boot)

6.使用事务的注意事项

1.事务的核心特性(ACID)

事务的可靠性由 ACID 保证,这是数据库设计的基石:

特性含义例子(转账:A 转 100 给 B)
原子性(Atomicity)事务是最小执行单位,不可拆分,要么全成,要么全败。A 扣 100 和 B 加 100 必须同时成功;若 B 加 100 失败,A 的扣款需回滚。
一致性(Consistency)事务执行前后,数据总状态保持合法(符合业务规则)。转账前 A+B 总余额 = 1000,转账后仍 = 1000,不会出现 “只扣不加”。
隔离性(Isolation)多个事务并发执行时,彼此的操作互不干扰,事务看到的数据是 “隔离” 的。事务 1(A 转 B)和事务 2(查询 A 余额)并发时,事务 2 看不到事务 1 未提交的中间状态。
持久性(Durability)事务提交后,修改永久生效,即使数据库崩溃(如断电),数据也不会丢失。事务提交后,A 的余额 - 100、B 的 + 100 永久保存,重启数据库后仍有效。

2.事务的使用场景

只要涉及 “多步操作需保证一致性” 的场景,都需要事务:

  • 金融转账(核心场景)
  • 订单创建(扣库存 + 生成订单 + 扣余额)
  • 账户注册(创建用户 + 初始化账户 + 发送通知)
  • 数据批量更新(如批量调整价格,需全部成功或全部失败)

3.事务的基本操作(SQL 层面)

事务的生命周期:开启事务 → 执行 SQL → 提交事务(成功)/ 回滚事务(失败)

3.1 开启事务

不同数据库语法略有差异,但核心一致:

-- MySQL
START TRANSACTION;  -- 或 BEGIN;
-- PostgreSQL
BEGIN;  -- 或 START TRANSACTION;
-- Oracle
BEGIN;  -- 或 SET TRANSACTION;

3.2 执行 SQL(核心业务逻辑)

执行 1 条或多条 SQL(增删改查,主要是增删改):

-- 示例:A(id=1)转100给B(id=2)
UPDATE account SET balance = balance - 100 WHERE id = 1;  -- A扣钱
UPDATE account SET balance = balance + 100 WHERE id = 2;  -- B加钱

3.3 提交事务(成功时)

事务中所有 SQL 执行无误后,提交事务,修改永久生效:

COMMIT;

3.4 回滚事务(失败时)

若执行过程中出现错误(如 SQL 语法错、业务逻辑不满足),回滚事务,所有修改撤销:

ROLLBACK;

3.5 保存点(进阶:部分回滚)

复杂事务中,可设置 “保存点”,仅回滚到指定保存点,而非整个事务:

-- 1. 开启事务
START TRANSACTION;
-- 2. 执行第一步SQL
UPDATE account SET balance = balance - 100 WHERE id = 1;  -- A扣钱
-- 3. 设置保存点
SAVEPOINT sp1;
-- 4. 执行第二步SQL(假设此处可能失败)
UPDATE account SET balance = balance + 100 WHERE id = 2;  -- B加钱
-- 5. 若第二步失败,回滚到保存点(仅撤销第二步,第一步仍保留)
ROLLBACK TO sp1;
-- 6. 若后续无错误,提交事务(仅A扣钱生效,需根据业务调整)
COMMIT;

4.不同数据库的事务差异(重点)

之前对话中提到的 PostgreSQL 与 MySQL,在事务上的核心差异的是 默认隔离级别

特性MySQL(InnoDB 引擎)PostgreSQL
默认隔离级别Repeatable Read(可重复读)Read Committed(读已提交)
并发性能略高(可重复读隔离级别下,锁竞争相对少)略低(读已提交隔离级别下,锁粒度更细)
幻读问题可重复读级别下,通过 MVCC 避免幻读读已提交级别下,可能出现幻读
事务块语法支持 BEGIN/START TRANSACTION + COMMIT/ROLLBACK支持 BEGIN + COMMIT/ROLLBACK,也支持事务块
保存点支持支持支持

5.实际开发中的使用(以 Java 为例)

5.1 原生 JDBC 实现事务

Connection conn = null;
try {// 1. 获取连接(关闭自动提交)conn = DriverManager.getConnection(url, user, pwd);conn.setAutoCommit(false); // 关键:关闭自动提交,开启手动事务// 2. 执行SQLString sql1 = "UPDATE account SET balance = balance - 100 WHERE id = 1";String sql2 = "UPDATE account SET balance = balance + 100 WHERE id = 2";conn.prepareStatement(sql1).executeUpdate();conn.prepareStatement(sql2).executeUpdate();// 3. 提交事务conn.commit();
} catch (Exception e) {// 4. 异常回滚if (conn != null) conn.rollback();e.printStackTrace();
} finally {// 5. 释放资源if (conn != null) conn.close();
}

5.2 框架层面(Spring Boot)

使用@Transactional注解,声明式事务(推荐):

@Service
public class TransferService {@Autowiredprivate JdbcTemplate jdbcTemplate;// 关键:添加@Transactional注解,Spring自动管理事务@Transactional(rollbackFor = Exception.class) // 出现任何异常都回滚public void transfer(int fromId, int toId, int amount) {// 执行转账逻辑jdbcTemplate.update("UPDATE account SET balance = balance - ? WHERE id = ?", amount, fromId);jdbcTemplate.update("UPDATE account SET balance = balance + ? WHERE id = ?", amount, toId);}
}

6.使用事务的注意事项

  1. 避免长事务:长事务会占用数据库连接,阻塞其他操作,甚至导致锁超时(如转账事务不要包含 “等待用户输入” 的逻辑)。
  2. 事务粒度适中:不要把无关操作放进同一个事务(如 “转账 + 日志记录” 可拆分,日志失败不影响转账),也不要把需要一致性的操作拆成多个事务。
  3. 注意隔离级别:根据业务选择隔离级别(如金融场景用 “可重复读” 保证数据一致性,普通查询场景用 “读已提交” 提升并发)。
  4. 异常必须回滚:开发中需确保 “任何业务异常都触发回滚”,避免出现 “部分提交” 的情况(如 Spring 的@Transactional需指定rollbackFor = Exception.class,默认仅回滚运行时异常)。
  5. 锁冲突处理:高并发场景下,事务可能因锁等待超时失败,需添加重试机制(如用 Spring 的@Retryable注解)。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询