mysql - MYSQL的ACID都是什么意思,底层是如何实现的?

118 阅读2分钟

世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。

  1. ACID
    A原子性:一个事务只有执行成功和失败回滚两种状态,没有中间态。
    C一致性:事务执行成功或失败,都不会破坏数据库的完整性约束。如,A给B转账,A转成功了,B一定会收到。
    I隔离性:一个事务对一个数据进行操作时,其他事务不允许对同一个数据进行操作。
    D持久性:事务执行完成后,对数据所做的操作持久的保存在数据库中,不允许回滚。
  2. 底层实现
    A原子性:事务执行有成功和失败两种情况,执行成功后,保存到数据库中,执行失败,会回滚。那么到底如何回滚呢,其实,专门有一个undo log日志,记录数据库的增、删、改操作,当事务执行失败时,会根据undo log日志进行逆操作,即,insert的逆操作是delete,delete的逆操作是insert,update的逆操作是update,这样就实现了数据库数据的回滚
    I隔离性:隔离性是通过读写锁和MVCC实现的
    事务的隔离级别有:
    Serializable: 序列化
    RepeatableRead: 可重复读
    ReadCommited: 读已提交
    ReadUnCommited: 读未提交
    读写锁,大家应该比较熟悉了:
    如果执行写操作时只允许一个线程操作,加写锁
    允许多个线程读取数据,加读锁
    MVCC(多版本并发控制)是对事务的版本控制,拿常用的InnoDB来说:
    每一行数据都有两个隐藏列:create_version, delete_version
    用来记录事务的版本
    每insert一次,create_version加1
    每delete一次,delete_version为当前事务的create_version
    每update一次,delete_version为当前事务的create_version,insert_version加1,相当于删除后新增。
    在读取数据时,如果没有delete_version,只读取create_version小于等于当前版本的数据,以保证事务开启时,当前数据已存在。
    如果有delete_version,会读取delete_version大于当前版本号的数据,以保证事务开启时,当前数据还没有被删除。
    D持久性:在InnoDB中有一个缓冲区,每次读数据时会先从缓冲区中读取,如果缓冲区中不存在,再从磁盘中读取;每次写数据时,先写入到缓冲区,然后同步到磁盘中。这样如果服务器突然宕机,可能造成缓冲中数据丢失,为了解决这个问题,在操作时,放入缓冲区的数据,同时会记录到redo log日志中,如果出现缓冲丢失,可以从redo logo日志中恢复
    C一致性:原子性、隔离性、持久性共同保证了一致性