【Mysql】事务、隔离级别以及ACID特性概念
数据库管理系统(DBMS)中的事务和隔离级别,通常会引用ACID属性。ACID代表原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability),这些属性是确保数据库中数据完整性和可靠性的关键要素。
1. 事务(Transaction)是什么?
- 事务是数据库操作单元,可以包含一个或多个数据库操作(例如插入、更新、删除等)。
- 事务的特点是要么全部成功提交,要么全部失败回滚,以确保数据的完整性。
- 事务通常用BEGIN TRANSACTION(或类似的命令)开始,然后使用COMMIT以提交更改,或使用ROLLBACK来撤消更改。
2. 隔离级别(Isolation Level)
- 隔离级别定义了多个并发事务之间的交互方式和可见性
- SQL标准定义了四种主要的隔离级别,从最低到高依次是:读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeatable Read)、和串行化(Serializable)
- 不同隔离级别决定了事务可以看到其他事务中的数据变化的程度,以及在并发操作中可能发生的问题。
(1)读未提交(Read uncommitted): 事务中的修改,即使没有提交,对其他事务也都是可见的
(2)读提交(read committed): 事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的
(3)可重复读(repeatable read): 一个事务按相同的查询条件读取以前检索过的数据,其他事务插入了满足其查询条件的新数据,会产生幻行
(4)串行化(Serializable): 强制事务串行执行
3.ACID特性:
- 原子性(Atomicity):原子性确保事务是不可分割的操作单元。事务要么全部成功,要么全部失败,没有中间状态。如果在事务执行过程中发生错误,将撤销事务的所有更改,以保持数据库一致。
- 一致性(Consistency):一致性确保事务执行前后数据库都必须保持一致状态。这意味着事务将数据库从一个一致状态转移到另一个一致状态,而不会破坏数据的完整性。
- 隔离性(Isolation):隔离性确保并发事务之间的相互影响最小化。不同的隔离级别决定了事务之间可见性和数据访问的方式,以避免数据损坏和不一致。
- 持久性(Durability):持久性确保一旦事务提交,其更改将在系统崩溃或故障后仍然存在。数据库将事务的更改保存在持久性存储介质(通常是硬盘)上,以确保数据的永久性。
4. 并发事务带来的问题:
- 脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的
- 丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。 例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
- 不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
- 幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
不可重复读和幻读区别: 不可重复读的重点是修改,幻读的重点在于新增或者删除。
例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。
例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读。
5 数据库事务的隔离级别对应解决的问题:
备注:
a. 事务隔离级别为读提交时,写数据只会锁住相应的行
b. 事务隔离级别为可重复读时,如果检索条件有索引(包括主键索引)的时候,默认加锁方式是next-key 锁;如果检索条件没有索引,更新数据时会锁住整张表。一个间隙被事务加了锁,其他事务是不能在这个间隙插入记录的,这样可以防止幻读
c. 事务隔离级别为串行化时,读写数据都会锁住整张表
d. 隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大