数据库事务基本要素ACID

数据库事务具有4个特征,分别是原子性一致性隔离性持久性,简称事务的ACID特性;

一、原子性(atomicity)

一个事务要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分操作,这就是事务的原子性

二、一致性(consistency)

事务的执行不能破坏数据库数据的完整性和一致性,一个事务在执行之前和执行之后,数据库都必须处于一致性状态。

如果数据库系统在运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成的事务对数据库所作的修改有一部分已写入物理数据库,这是数据库就处于一种不正确的状态,也就是不一致的状态

三、隔离性(isolation)

事务的隔离性是指在并发环境中,并发的事务时相互隔离的,一个事务的执行不能不被其他事务干扰。不同的事务并发操作相同的数据时,每个事务都有各自完成的数据空间,即一个事务内部的操作及使用的数据对其他并发事务时隔离的,并发执行的各个事务之间不能相互干扰。

在标准SQL规范中,定义了4个事务隔离级别,不同的隔离级别对事务的处理不同,分别是:未授权读取,授权读取,可重复读取和串行化

1、读未提交(Read Uncommited)

,该隔离级别允许脏读取,其隔离级别最低;比如事务A和事务B同时进行,事务A在整个执行阶段,会将某数据的值从1开始一直加到10,然后进行事务提交,此时,事务B能够看到这个数据项在事务A操作过程中的所有中间值(如1变成2,2变成3等),而对这一系列的中间值的读取就是未授权读取

2、授权读取或称读已提交、不可重复读(Read Commited)

授权读取只允许获取已经提交的数据。比如事务A和事务B同时进行,事务A进行+1操作,此时,事务B无法看到这个数据项在事务A操作过程中的所有中间值,只能看到最终的10。另外,如果说有一个事务C,和事务A进行非常类似的操作,只是事务C是将数据项从10加到20,此时事务B也同样可以读取到20,即授权读取允许不可重复读取。

3、可重复读(Repeatable Read)

就是保证在事务处理过程中,多次读取同一个数据时,其值都和事务开始时刻是一致的,因此该事务级别禁止不可重复读取和脏读取,但是有可能出现幻影数据。所谓幻影数据,就是指同样的事务操作,在前后两个时间段内执行对同一个数据项的读取,可能出现不一致的结果。在上面的例子中,可重复读取隔离级别能够保证事务B在第一次事务操作过程中,始终对数据项读取到1,但是在下一次事务操作中,即使事务B(注意,事务名字虽然相同,但是指的是另一个事务操作)采用同样的查询方式,就可能读取到10或20;

4、串行化

是最严格的事务隔离级别,它要求所有事务被串行执行,即事务只能一个接一个的进行处理,不能并发执行。

关于隔离性分为4种:(事务A、B开启,B先提交会有以下情况)

  1. 读未提交(read-uncommitted)

会发生脏读 (B事务还没有提交,A已经查询到B操作之后的结果)

  1. 不可重复读(读已提交)(read-committed)

oracle默认级别 (B提交事务,A两次查询结果不同)

  1. 可重复读(repeatable-read)

mysql默认级别 (B提交事务,A两次查询结果相同)

  1. 串行化(serializable)

mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。

以前看过这篇文章写得很详细:
https://www.cnblogs.com/huanongying/p/7021555.html

四、持久性(durability)

一旦事务提交,那么它对数据库中的对应数据的状态的变更就会永久保存到数据库中。–即使发生系统崩溃或机器宕机等故障,只要数据库能够重新启动,那么一定能够将其恢复到事务成功结束的状态

隔离性实现原理

上面已经大体描述了隔离级别的含义,下面我们就来具体看下MySQL是如何实现事务隔离性的?简单来说,在MySQL中,事务的隔离性是通过锁来实现的。MySQL中有三种行锁算法,Record Lock(单行锁定),Gap Lock(间隙锁)和Next-Key Locking(Record+Gap)。在讲之前,还需要说到一个MySQL的特点,那就是MySQL有两种读取数据的模式,一种是一致性非锁定读,另一种是一致性锁定读。

先说一下一致性锁定读:

1)SELECT … FOR UPDATE (显式加写锁)
2)SELECT … LOCK IN SHARE MODE (显式加读锁)

再谈一下一致性非锁定读:

一致性非锁定读的含义是当事务读取的某行数据被其他事务锁定时,可以不用等待锁释放,而是读取此行的一个具有一致性的数据快照,而这个快照数据就存储在undo日志中。这种一行数据有多个版本的技术也叫做MVCC,即多版本并发控制。MVCC也是一个通用概念,有多种实现方式,MySQL是通过undo日志来实现的MVCC。

接下来我们继续讲解MySQL是如何实现四个隔离级别的:

  1. 未提交读:显然不需要对行加锁,这样其他事务就可以同时访问此行。
  2. 提交读:在InnoDB的默认配置下,此隔离级别采用一致性非锁定读模式。即如果此行正被其他事务锁定,那么MySQL通过MVCC技术,当前事务可以读取此行的一个最近提交的快照数据。
  3. 可重复读:在InnoDB的默认配置下,此隔离级别采用一致性非锁定读模式。MySQL通过Next-Key Locking锁定一个范围,使范围内的数据不能同时在其他事务中插入,避免了当前事务出现“幻行”问题。MySQL通过MVCC,在读取某行数据时,如果此行被其他事务锁定,则当前事务不用阻塞,直接读取当前事务开始时的此行的一个数据快照,来解决可重复读问题。即在整个事务中,读取的始终是此行的同一个数据快照。MySQL的可重复读已经达到了SQL标准的Serializable标准,即(无脏读,可重复读MVCC,无幻读Next-Key Locking)。
  4. 串行化:串行化执行事务,即发现有其他事务正在操作此行,则此事务阻塞直到其他事务结束。MySQL会对每个select加上lock in share mode,不支持一致性非锁定读。

扩展:我们在真实使用事务的时候,常见场景有通过Spring配置数据源,配置ORM映射框架例如Mybatis,在使用事务的时候本质上是利用数据库的API,例如对于MySQL来说是begin, commit和rollback等。获取数据库连接,开启事务,提交事务等。Spring中的事务传播机制属于Spring自己的概念,本质上为根据不同的事务传播机制确定是否利用同一个连接,或者是否将多个事务逻辑通过同一个Connection或者多个Connection中来提交或者回滚,有兴趣的可以看下Mybatis关于事务的源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值