事务ACID特性及4种隔离级别详解

事务是指对系统进行的一组操作,为了保证系统的完整性,事务需要具有ACID特性,具体如下:

  • 原子性(Atomic)

    一个事务包含多个操作,这些操作要么全部执行,要么全都不执行。实现事务的原子性,要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。
    回滚实际上是一个比较高层抽象的概念,大多数DB在实现事务时,是在事务操作的数据快照上进行的(比如,MVCC),并不修改实际的数据,如果有错并不会提交,所以很自然的支持回滚。
    而在其他支持简单事务的系统中,不会在快照上更新,而直接操作实际数据。可以先预演一边所有要执行的操作,如果失败则这些操作不会被执行,通过这种方式很简单的实现了原子性。

  • 一致性(Consistency)

    一致性是指事务使得系统从一个一致的状态转换到另一个一致状态。事务的一致性决定了一个系统设计和实现的复杂度。事务可以不同程度的一致性:
    强一致性:读操作可以立即读到提交的更新操作。
    弱一致性:提交的更新操作,不一定立即会被读操作读到,此种情况会存在一个不一致窗口,指的是读操作可以读到最新值的一段时间。
    最终一致性:是弱一致性的特例。事务更新一份数据,最终一致性保证在没有其他事务更新同样的值的话,最终所有的事务都会读到之前事务更新的最新值。如果没有错误发生,不一致窗口的大小依赖于:通信延迟,系统负载等。
    其他一致性变体还有:
    单调一致性:如果一个进程已经读到一个值,那么后续不会读到更早的值。
    会话一致性:保证客户端和服务器交互的会话过程中,读操作可以读到更新操作后的最新值。

  • 隔离性(Isolation)

    并发事务之间互相影响的程度,比如一个事务会不会读取到另一个未提交的事务修改的数据。在事务并发操作时,可能出现的问题:

    • 脏读:
      • 事务A修改了一个数据,但未提交,事务B读到了事务A未提交的更新结果,如果事务A提交失败,事务B读到的就是脏数据。
    • 不可重复读:
      • 在同一个事务中,对于同一份数据读取到的结果不一致。比如,事务B在事务A提交前读到的结果,和提交后读到的结果可能不同。不可重复读出现的原因就是事务并发修改记录,要避免这种情况,最简单的方法就是对要修改的记录加锁,这回导致锁竞争加剧,影响性能。另一种方法是通过MVCC可以在无锁的情况下,避免不可重复读。
    • 幻读:
      • 在同一个事务中,同一个查询多次返回的结果不一致。事务A新增了一条记录,事务B在事务A提交前后各执行了一次查询操作,发现后一次比前一次多了一条记录。幻读是由于并发事务增加记录导致的,这个不能像不可重复读通过记录加锁解决,因为对于新增的记录根本无法加锁。需要将事务串行化,才能避免幻读。
  • 持久性(Durability)

    • 事务提交后,对系统的影响是永久的。

事务的隔离级别从低到高有:

  • Read Uncommitted(读未提交):
    • 最低的隔离级别,什么都不需要做,一个事务可以读到另一个事务未提交的结果。所有的并发事务问题都会发生。
  • Read Committed(读已提交):
    • 只有在事务提交后,其更新结果才会被其他事务看见。可以解决脏读问题。
  • Repeated Read(重复读):
    • 在一个事务中,对于同一份数据的读取结果总是相同的,无论是否有其他事务对这份数据进行操作,以及这个事务是否提交。可以解决脏读、不可重复读。
  • Serialization(串行化):
    • 事务串行化执行,隔离级别最高,牺牲了系统的并发性。可以解决并发事务的所有问题。
      通常,在工程实践中,为了性能的考虑会对隔离性进行折中。

ANSI/ISO SQL标准定义了4种事务隔离级别,这些隔离级别是根据事务并行出现的4个“现象”定义的。
4个现象是:

  • 1.更新丢失(Lost Update):A和B同时写

    例:
    1.事务A将数值改为1并提交;
    2.事务B将数值改为2并提交。
    这时数据的值为2,事务A所做的更新将会丢失。
    解决办法:对行加锁,只允许并发一个更新事务。

  • 2.脏读(dirty read):A改后还未提交,B读,A又改并提交

    例:
    1.Mary的原工资为1000, 财务人员将Mary的工资改为了8000(但未提交事务)
    2.Mary读取自己的工资 ,发现自己的工资变为了8000,欢天喜地!
    3.而财务发现操作有误,回滚了事务,Mary的工资又变为了1000, 像这样,Mary记取的工资数8000是一个脏数据。

  • 3.不可重复读(nonrepeatable read):A先读,B再改,A再读

    例:
    1.在事务A中,Mary 读取了自己的工资为1000,操作并没有完成
    2.在事务B中,这时财务人员修改了Mary的工资为2000,并提交了事务.
    3.在事务A中,Mary 再次读取自己的工资时,工资变为了2000
    解决办法:如果只有在修改事务完全提交之后才可以读取数据,则可以避免该问题。

  • 4.幻读(phantom read):A改后还未提交,B改其他的,A再查

    例:
    1.A把所有的“黑色”改为“白色”
    2.B把所有的“红色”改为“黑色”
    3.A再查询黑色,却发现还有一批。

根据对4个现象的避免程度,事务的4个隔离级别是:

  • Read Uncommited:读未提交数据(解决了更新丢失)
  • Read Commited:读已提交的数据(解决了更新丢失、脏读)
  • Repeatable Read:可重复读(解决了更新丢失、脏读、不可重复读)
  • Serializable:串行化(全部解决了)

四个级别与四种现象的关系是:

英文更新丢失脏读不可重复读幻读
Read Uncommited 读未提交不会出现会出现会出现会出现
Read Commited 读已提交不会出现不会出现会出现会出现
Repeatable Read 可重复读
不会出现不会出现不会出现会出现
Serializable 串行化不会出现不会出现不会出现不会出现

大多数数据库的默认隔离级别为: Read Commited,如Sql Server , Oracle
少数数据库默认的隔离级别为Repeatable Read, 如MySQL InnoDB存储引擎

tr_isolation(隔离)参数:
可以设置mysql的隔离级别

这里写图片描述

tr_isolation:可选值有

  • READ-UNCOMMITED
  • READ-COMMITED
  • REPEATABLE-READ
  • SERIALIZABLE

Create By LPeng

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

斯言甚善

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

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

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

打赏作者

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

抵扣说明:

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

余额充值