ACID

ACID指数据库事务正确执行的四个基本要素:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务的数据库系统,必须要具备这四种特性,否则在事务过程中无法保证数据的正确性。

  • A-原子性:整个事务中的所有操作要么全部完成,要么全部失败,不可能停沚在中间的某个环节。事务在执行过程中发生错误,会被回滚到事务开始前的状态,就像事务从来都没有执行过一样。
  • C-一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
  • I-隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务运行在相同的时间内,执行相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。
  • D-持久性:在事务完成以后该所对数据库所作的更改便持久的保存到数据库中,并不会被回滚。

    目前主要有两种方式实现ACID:第一种是write ahead logging;第二种是Shadow paging。
    推荐阅读
    write ahead logging
    Shadow paging


使用事务的隔离级别如何能够保障事务的原子性呢?

这个问题不好,简单介绍一下这个问题的来源,是我在看mysql专栏关于隔离级别那节的时候突然提出来的,这就像如果有一把锤子就看所有的问题都是钉子。其实我想问的问题是:如果设定了某个级别的隔离,数据库在原子性这块是如何处理的呢。还是有点疑惑吧?想象一下,在程序中设定某个服务隔离级别为读已提交,且该段程序多次写入数据库。我不知道这两种情况是否可以归成一个,总之就是想了解这块倒底是如何实现的:
个人理解:原子性和隔离性都是mysql数据库的四大特性的内容,从大的方面说是如何更清晰的表述四大特性之间的关系问题,从小的方面呢,就是上面我对问题的描述了。咱们先从小的方面,事务中的所有操作都可以被看作是一个逻辑单元,这个单元的操作要么全部成功,要么全部失败。在此基础上再对事务做隔离级别的限制,结果就是按照隔离级别的要求各终端会得到不同的内容。有点费解了吧,可以把事务看是一个盒子,原子性是对盒子里面的内容进行控制,而隔离性是对该盒子进行装饰。再从大的方面来看一下,一致性是mysql四大特性中最基本的属性,其他三个属性都是为保证一致性而存在的。原子性的实现需要通过日志,将所有对数据库的更新操作都写入日志,如果事务中一部分操作成功了,但另一部分无法继续,则可以通过回溯日志将已经成功的操作撤销,从而达到操作全部失败的效果。很显然如果只保证了事务的原子性,数据的一致性还是无法满足的因为会有并发访问的情况(例如两个事务同时对同一条记录进行操作),为了保证这种情况下的一致性,这时隔离性就开始产生作用,它能保证每一个事务所看到的数据总是一致的,这句话可以理解为,多个事务并发执行后的状态,和它们串行执行后的状态是等价的。
推荐阅读
MySQL 四种隔离性测试


事务的隔离级别?

  • Isolation.Read uncommitted
  • Isolation.Read committed
  • Isolation.Repeatable read
  • Isolation.Serializable

低层是如何实现的,加上事务隔离级别之后就可以啦?
这问题多小白呀,前半句像大神,后半句像大白。就来说说实现吧:两种类型的锁,1、悲观锁,当前事务将所有涉及操作的对象加锁,操作完成后释放给其它对象使用。为了尽可能 提高性能,发明了各种粒度的锁(数据库级/表级/行级等)/各种性质(共享锁/排它锁/共享意向锁/排他意向锁等)。为了解决死锁问题,又发明了两个阶段锁协议/死锁检测等一系列技术。2、乐观锁,不同的事务可以看到同一对象的不同历史版本,如果有两个事务同时修改了同一行数据,那么在较晚的事务提交时进行冲突检测。实现也有两种,一种是通过日志UNDO的方式来获取数据行的历史版本,一种是简单地在内存中保存同一个数据行的多个历史版本,通过时间戳来区分。