ACID

本文深入探讨了数据库事务的ACID原则,包括原子性、一致性、隔离性和持久性,以及事务隔离级别的概念,如脏读、不可重复读和幻读等问题的解决方案。

有引用

上周在学Prisma的时候在它的官方文档中看到了一个ACID,今天来学习一下~

what 事务 ❓

事务是访问数据库的一个操作序列,数据库应用系统通过事务集来完成对数据库的存取。事务的正确执行使得数据库从一种状态转换为另一种状态

ACID 即 事务管理

事务必须服从ISO/IEC所制定的ACID原则

Atomicity 即 原子性

事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生(you jump,I jump😂)

上图中表示的意思是:当A给B转账200的时候,要么转账成功,A少了200,B多了200。要么转账失败,A和B都没有资金流动。

Consistency 即 一致性

事务前后数据的完整性必须保持一致
还是上面的那个图,这里👇
操作前A:800,B:200
操作后A:600,B:400

一致性表示事务完成后,符合逻辑运算

Isolation 即 隔离性

事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离

针对多个用户同时操作,主要是排除其他事务对本次事务的影响

两个事务同时进行,其中一个事务读取到另外一个事务还没有提交的数据

### Durability 即 持久性 持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

表示事务结束后的数据不随着外界原因导致数据丢失

操作前A:800,B:200 操作后A:600,B:400 如果在操作前(事务还没有提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为 A:800,B:200 如果在操作后(事务已经提交)服务器宕机或者断电,那么重启数据库以后,数据状态应该为 A:600,B:400

事务隔离级别

事务隔离级别,就是为了解决上面几种问题而诞生的。为什么要有事务隔离级别,因为事务隔离级别越高,在并发下会产生的问题就越少,但同时付出的性能消耗也将越大,因此很多时候必须在并发性和性能之间做一个权衡。所以设立了几种事务隔离级别,以便让不同的项目可以根据自己项目的并发情况选择合适的事务隔离级别,对于在事务隔离级别之外会产生的并发问题,在代码中做补偿

  • 脏读

就是指事务A读到了事务B还没有提交的数据,比如银行取钱,事务A开启事务,此时切换到事务B,事务B开启事务–>取走100元,此时切换回事务A,事务A读取的肯定是数据库里面的原始数据,因为事务B取走了100块钱,并没有提交,数据库里面的账务余额肯定还是原始余额,这就是脏读

  • 不可重复读

就是指在一个事务里面读取了两次某个数据,读出来的数据不一致。还是以银行取钱为例,事务A开启事务–>查出银行卡余额为1000元,此时切换到事务B事务B开启事务–>事务B取走100元–>提交,数据库里面余额变为900元,此时切换回事务A,事务A再查一次查出账户余额为900元,这样对事务A而言,在同一个事务内两次读取账户余额数据不一致,这就是不可重复读

  • 虚读(幻读)
    就是指在一个事务里面的操作中发现了未被操作的数据。比如学生信息,事务A开启事务–>修改所有学生当天签到状况为false,此时切换到事务B,事务B开启事务–>事务B插入了一条学生数据,此时切换回事务A,事务A提交的时候发现了一条自己没有修改过的数据,这就是幻读,就好像发生了幻觉一样。幻读出现的前提是并发的事务中有事务发生了插入、删除操作

隔离级别的设置

设置含义
DEFAULT默认隔离级别,每种数据库支持的事务隔离级别不一样,如果Spring配置事务时将isolation设置为这个值的话,那么将使用底层数据库的默认事务隔离级别
READ_UNCOMMITTED即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种,因此很少使用
REPEATABLE_READ重复读取,即在数据读出来之后加锁,类似"select * from XXX for update",明确数据读取出来就是为了更新用的,所以要加一把锁,防止别人修改它。REPEATABLE_READ的意思也类似,读取了一条数据,这个事务不结束,别的事务就不可以改这条记录,这样就解决了脏读、不可重复读的问题,但是幻读的问题还是无法解决
SERLALIZABLE串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了
事务的 ACID 属性是数据库事务处理的基石,确保了事务的可靠性和数据的完整性,共同定义了事务应该如何表现,以及数据库管理系统应该如何处理事务。理解和应用这些属性对于设计和实现可靠的数据库应用程序至关重要[^1]。ACID 属性具体介绍如下: - **原子性(Atomicity)**:即事务的不可分割性,事务中的操作要么全做,要么全不做。例如在银行转账操作中,从一个账户扣款和向另一个账户入账这两个操作必须作为一个整体完成,如果其中一个操作失败,整个事务将回滚,就像什么都没发生一样[^3]。 - **一致性(Consistency)**:一个事务在执行前后,数据必须处于正确的状态,满足完整性约束。例如,在一个数据库表中,规定 A 列的值和 B 列的值之和必须等于 100,那么在事务执行前后,这个约束都必须满足。如果一个事务试图破坏这个约束,数据库管理系统将阻止该事务的执行[^2][^3]。 - **隔离性(Isolation)**:多个事务并发执行时,一个事务的执行不应该影响其他事务的执行。不同的隔离级别会对事务之间的相互影响程度进行控制,常见的隔离级别有读未提交、读已提交、可重复读和串行化。例如,在一个高并发的电商系统中,多个用户同时进行下单操作,每个用户的下单事务应该相互隔离,互不干扰[^3]。 - **持久性(Durability)**:事务处理完成后,对数据的修改就是永久的,即便系统故障也不会丢失。例如,当一个用户成功完成一笔银行转账后,即使数据库所在的服务器突然断电,这笔转账记录也不会丢失,因为数据库会将事务的修改持久化到磁盘等存储设备中[^3]。 下面是一个简单的 Java JDBC 示例,展示了如何使用事务的 ACID 属性: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; import java.sql.Statement; public class TransactionExample { public static void main(String[] args) { Connection conn = null; Statement stmt = null; try { // 1. 获取数据库连接 conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/testdb", "root", "password"); // 2. 开启事务 conn.setAutoCommit(false); stmt = conn.createStatement(); // 3. 进行数据库操作 String sql1 = "update user_table set balance = balance - 100 where user='AA'"; stmt.executeUpdate(sql1); // 模拟网络异常 // System.out.println(10 / 0); String sql2 = "update user_table set balance = balance + 100 where user='BB'"; stmt.executeUpdate(sql2); // 4. 若没有异常,则提交事务 conn.commit(); } catch (Exception e) { e.printStackTrace(); // 5. 若有异常,则回滚事务 try { if (conn != null) { conn.rollback(); } } catch (SQLException e1) { e1.printStackTrace(); } } finally { try { // 6. 恢复每次 DML 操作的自动提交功能 if (conn != null) { conn.setAutoCommit(true); } } catch (SQLException e) { e.printStackTrace(); } // 7. 关闭连接 try { if (stmt != null) { stmt.close(); } if (conn != null) { conn.close(); } } catch (SQLException e) { e.printStackTrace(); } } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值