事务与ACID

  • 事务

    事务就是一组原子性的SQL查询,或者说一个独立的工作单元。如果数据库引擎能够成功的对数据库应用该组查询的全部语句,那么就执行改组查询。如果其中有任何一条语句因为崩溃或者其他原因无法执行,那么所有的语句都不会被执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。

  • ACID

    ACID 表示__原子性__(Atomicity)、一致性(Consistency)、独立性(Isolation)、持久性(Durability)
    一个运行良好的事务处理系统,必须具备这些标准特征。

    • 原子性(Atomicity)
      一个事务必须被视为是一个最小的不可分割的最小工作单元,整个事务中的所有操作要么全部都提交成功,要么全部都失败,对于一个事务来说,,不可能只执行其中的一部分操作,这就是事务的原子性。
      重点是其中的不可拆分,一个事务从开始到最后运行过程中不可以再被拆分。即使是一组操作(多次查询)只要是一个事务中,也不能将一组操作拆分成多组。
      举例:
      A、B、C、D 四个操作在一个事务a中,那么对于事务处理系统来说,A、B、C、D四个操作就相当于一个操作,必须是A、B、C、D四个操作一次性完成并且一次性都成功才能算是当前事务a成功。在其中任何一个操作失败了整个事务都将被认为失败。

    • 一致性(Consistency)
      数据库总是从一个一致的状态转换为另一个一致的状态。
      数据在修改的时候,通过事务操作,在事务提交之前数据库一直保持着原始的状态,事务操作中假设执行了四条查询,其中前两条成功第三条第四条失败,导致整个事务是失败的,那么一致性就要求,第一条第二条成功的也不会修改当前数据库状态。因为事务没有提交,所以不会将修改的数据写入数据库。也可以说,数据库的数据在事务提交前保持原有状态但是事务提交之后,数据就必须修改为事务中修改了之后的状态。
      事务提交要么成功要么失败,同时数据库状态也保持要么提交前要么提交后,这两者必须对应。发生修改的转折点在于事务提交而不在于查询的执行。
      举例:
      A、B、C、D 四个操作在一个事务a中,A、B成功执行了,然后C执行失败,那么此时事务是失败的,那么这个时候已经执行了的A、B操作对原来的数据库状态不应该有任何影响,也就是A、B的修改不可能被看到,及时已经操作成功了,因为整个事务是失败的。其实也就是原子性的体现。假设A、B、C、D均成功,并且事务也已经成功提交了,那么数据库的状态应该与事务提交前的操作成功之后的保持一致。也就是说 假设事务b修改了某字段的值为 1 那么事务执行成功并且提交成功了那么这个字段的值就只可能是1 而不会被事务b修改为别的数据。即提交的前后需要保持一致。

    • 独立性(Isolation)
      通常来水,一个事务所有的修改在最终提交之前,对其他事物是不可见。也就是事务A,相对于事务B来说是独立的,A不可见到B, B同时也不可见到A。
      涉及隔离级别的问题,之后在单独拿出来讨论。

    • 持久性(Durability)
      事务一旦提交,那么其修改将是永久的,再次查询的结果必须是提交事务之后的结果。及时系统奔溃,修改了的数据也不会丢失。
      个人理解,持久性本身就是极端要求的,因为数据的丢失有时候是不可控的,只能尽量避免,100%保证数据永久存在的方案理论上不存在,及时备份,也可能备份丢失。

  • ACID小结
    个人理解,ACID是一个理想化,的很纯净的事务系统的标准。持久性其实永远存在风险,这个只能根据具体情况具体理解其中的含义。原子性和一致性,应该是最基本的要求,隔离型也需要根据实际的情况来分析,结合业务谈才有意义。

  • 事务隔离级别

    • 未提交读(Read Uncommitted)
      字面直接理解,读到了没有提交的事务的操作。也就是说,对于不同的事务之间是可以读取到相互修改了并且没有提交的数据,直接造成的就是脏读。造成的问题很多:
      举例:事务a 、b读取了同一个记录的同一个数据字段value,初始值为1

      1. a事务先读取并且修改value为0,但是没有还没提交事务
      2. 这个时候b来读取,读到了value,值为0
      3. b的逻辑就是假设数据库数据是 1 那么改为2,发现value值是0,
      4. 那么b就不修改,然后结束操作。

      可以很明显看出来,a事务的操作直接影响到了b的逻辑,这导致了很多在数据上的修改会出现不可预知的错误。

    • 提交读(Read Committed)
      字面直接理解,就是可以读取到提交了的事务作出的修改。
      a事务提交之后 就可以对后续的所有事物可见,但是在没有提交之前是对别事务不可见的。这个级别也叫组不可重复读。为什么这么叫是因为这个级别虽然隔离了一些没有提交的事务但是还是有问题存在。所谓不可重复读,就是读到了别事务提交的数据。
      举例:还是事务a、事务 b,事务a查询某一条记录的value字段,事务b修改这一记录的value字段。

      1. a事务查询 得到value为0
      2. b事务开始,修改了value 的值为1,并提交了事务
      3. a事务再次查询,得到的值为1

      可见a事务在自己的两个查询操作里面查询到了不一样的数据。这也会影响到原有的逻辑,也会造成不可预知的错误。
      大多数事务管理系统的的默认隔离级别就是提交读

    • 可重复度(Repeatable Read)
      这个级别保证了一个事务内,多次读取同样记录的结果是一致的。但是理论上,可重复读还是会存在问题。这一问题称之为幻读,指的是当某个事务在读取某一个范围内的记录时,另外一个事务在这一范围内插入了新的数据,并且提交了事务,这个时候当当前事务再次读取这一范围内的数据的时候就会出现欢行。
      举例:依旧是事务a、事务 b,事务a查询value字段大于10的记录,事务b新增一条value为20的记录。

      1. a事务查询 得到记录100条
      2. b事务开始,新增了记录 并提交了事务。
      3. a事务再次查询,得到记录 101条

      这个就是幻读的直接现象,当然一些数据库引擎已经通过多版本并发控制(MMVC)解决了这个问题,但是依旧不能否认这个问题的存在。

    • 可串行化(Serializable)
      目前认为的最高的隔离级别,他会强制所有事务进行串行化运行,来避免幻读的问题。这个级别会在读取的每一行数据上都加锁。这个很明显会造成大量的超时和锁争用问题,性能肯定会受到很大影响。

  • 总结

隔离级别脏读可能性不可重复读可能性幻读可能性加锁读
未提交读
提交读
可重复度
可串行化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值