数据库ACID

1.事务是什么?

  数据库的事务是一种机制、一个操作序列,包含了一组操作命令。事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么都执行,要么都不执行,因此事务是一个不可分割的工作逻辑单元。

  在数据库上执行并发操作时,事务是作为最小的控制单元来使用的,特别适用于多用户同时操作的数据库系统。

  事务具有四个特性ACID,即原子性(Automicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)

  一致性是最基本的属性,其他三个属性都是为了保证数据一致性而存在的。

2.ACID

  1.一致性:当事务完成后,数据必须处于一致状态。也就是说在事务开始之前,数据库中存储的数据处于一致状态。在正在进行的事务中 ,数据可能处于不一致的状态,比如数据可能有部分被修改。然而,当事务成功完成时,数据必须再次回到已知的一致状态 。通过书屋对数据所做的修改不能损坏数据,或则说事务不能使数据存储处于不稳定的状态。
  比如账户A有200元,账户B有200元,此时两人的余额总额是400元,此时A账户给B账户转了100元,此时A有100元,B有300元,此时的余额总额还是400元,也就是事务提交完成后再次回到一致性状态,而如果此时B的数据没有变,则成账户的总额处于不一致状态。

  2.原子性:事务是一个完整的操作。事务的各元素是不可分的。十五中的所有元素必须作为一个整体提交或则回滚。如果事务中的任何元素失败,则整个事务将失败。

  以银行转账事务为例:如果该事务提交了,则这两个账户的数据都将会更新。如果由于某种原因,事务在成功更新这两个账户之前终止了,则不会更新这两个账户的余额。

  为了实现原子性,需要通过日志:将所有对数据的更新操作都写入日志,如果一个事务中的一部分操作已经成功,但以后的操作,由于断电、系统崩溃、其他软件错误而无法继续,则通过回溯日志,将已经执行成功的操作撤销,从而达到“全部操作失败的”目的。

  但是原子性并不能完全保证一致性。在多个事务并行进行的情况下,即使保证了每一个事务的原子性,仍然可能导致数据不一致的结果。例如:事务1需要将100元转入账号A:此时将先读取账号A的值,然后再这个值的基础上加上100。但是在事务1操作的时候,另一个事务2也修改了账号A的值,为它增加了100元。那么最后的结果应该是增加200元。但是事实上,账号A只增加了100元,因为事务2操作的结果被事务1覆盖了。

  为了保证并发情况下的一致性,引入了隔离性。

  3.隔离性:对数据进行修改的所有并发事务是彼此隔离的,这表明事务必须是独立的,它不应以任何方式依赖于或影响其它事务。

  那么隔离性是怎么实现的呢?那当然是加锁了,原则上无非是两种锁:悲观锁和乐观锁
  悲观锁是什么呢?就向它的字面意思,对数据的操作总是持有悲观的态度,直白一点就是想着总会发生冲突,因此只要对数据进行操作,就对其进行加锁。常见的悲观锁:行锁、表锁、读锁、写锁
  乐观锁是什么呢?乐观锁就是持有乐观的态度,对数据进行操作是不会对其进行加锁,只有在对数据进行提交的时候,才会通过一种机制来验证数据是否存在冲突。 通常通过cas和版本号来实现冲突验证。

  数据库事务有不同的隔离级别,不同的隔离级别 对锁的使用是不同的,锁的应用最终导致不同事务的隔离级级别:
  读未提交:锁的释放实在事务提交之前,也就是数据修改完成后,锁就释放了。会出现脏读、不可重复读、幻读
  读已提交:锁的释放放在事务提交之后,解决了脏读、但是还存在不可重复读、幻读。(大多数数据的默认隔离级别)
  可重复读:采用的是MVCC(多版本并发控制),解决了脏读、不可重复读,但是还存在幻读。(Mysql数据库的默认隔离级别)
  序列化:(加了表锁)解决了所有问题

  脏读:比如事务A更新了一条数据,此时事务A还未提交事务,事务B对该条数据进行了读取,但是事务A进行了事务回滚,然后提交了事务,此时事务B读的数据就是错误的或则无用的数据,这种现象就叫做脏读。
  不可重复读:比如事务A对一条数据进行一次查询,此时事务B对当前数据记录进行修改,事务B提交事务后,A再对表进行查询,发现和上次查询的结果不同。这种现象称为不可重复读。
  幻读:比如事务A往表中插入了一条数据,但是还未提交,此时事务B对该表进行查询,并没有发现A插入的这条数据,此时事务A提交事务,事务B再次对表进行查询发现查询的结果和上次查询的结果不同。这种现象称为幻读。

  注意:幻读和不可重复读都是读取了一个已经提交的事务,所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体。

  4.持久性:事务的持久性是指不管系统是否发生了故障,事务处理的结果都是永久的。也就是说,一旦事务被提交,事务对数据所做的任何变动都会被永久的保存在数据库中。

### 数据库 ACID 特性详解 #### 1. 原子性(Atomicity) 原子性确保事务中的所有操作要么全部完成,要么完全不执行。如果事务在执行过程中发生错误或中断,则整个事务将被回滚到初始状态,以保证数据的一致性和完整性[^1]。例如,在银行转账场景中,如果从账户 A 转账到账户 B 的过程中出现故障,原子性会确保资金不会丢失,且两个账户的状态恢复到事务开始之前的状态[^3]。 #### 2. 一致性(Consistency) 一致性要求事务的执行必须使数据库从一个一致状态转换到另一个一致状态。这意味着事务不能破坏数据库的完整性约束,包括外键、唯一性等规则[^2]。例如,如果数据库中存在一个规则:用户的余额不能为负数,那么任何事务都不能违反这一规则[^1]。 #### 3. 隔离性(Isolation) 隔离性确保多个事务并发执行时,每个事务都像在单独的系统中运行一样,彼此之间互不干扰。这通过事务隔离级别来实现,常见的隔离级别包括读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)和串行化(Serializable)[^4]。隔离性可以防止脏读、不可重复读和幻读等问题,从而保证数据的正确性和一致性。 #### 4. 持久性(Durability) 持久性表示一旦事务成功提交,其对数据库的更改将永久保存,即使系统发生故障也不会丢失。这种特性通常通过写入日志文件或存储在非易失性介质上来实现。例如,在事务提交后,即使数据库服务器突然断电,重启后仍然能够恢复已提交的数据[^1]。 ```python # 示例代码:使用 SQL 实现事务处理 try: # 开始事务 connection.begin() # 执行一系列操作 cursor.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1;") cursor.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2;") # 提交事务 connection.commit() except Exception as e: # 如果发生异常,回滚事务 connection.rollback() raise e ``` 上述代码展示了如何通过编程语言数据库交互时实现事务的 ACID 特性。通过 `connection.begin()` 开始事务,并在成功完成后调用 `connection.commit()` 提交事务。如果发生异常,则调用 `connection.rollback()` 确保数据恢复到事务开始前的状态。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Listen·Rain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值