如何实现事务的 ACID 特性

作者:guoxj
浏览:410

事务的 ACID 特性是由关系数据库管理系统来实现的。

DBMS 采用 日志 来保证事务的 原子性、一致性 和 持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。

DBMS 采用 锁机制 来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许 持有锁的事务 能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。




登录后回复

共有1条评论


guoxj

    归档日志 bin log
    回滚日志 undo log
    重做日志 redo log
    原子性:
        undo log日志记录sql操作,当发生回滚时,逆序执行逆操作来完成回滚
    持久性:
        bin log & redo log日志,
        redo log: 为了避免每次读取数据都进行磁盘IO,MySQL的InnoDB引擎采用缓存buffer方式
        redo log分为两个部分:缓冲区的redolog buffer和磁盘上的redologfile
        磁盘上的redo log不受宕机影响,在每次真正执行DML操作之前先更新redo log(称为预写式日志),也就是WAL技术
            WAL技术(Write-Ahead Logging):在真正把数据写入到磁盘前,先记录日志
            redo log(undo log跟redo log的机制一样)都经历一次写,一次刷
                写过程将引擎用户层buffer记录的数据写入核心层buffer
                刷过程将核心层buffer数据真正写入磁盘
            由此分为三种写刷时机,同样由参数控制:延迟写 / 实时写,实时刷 / 实时写,延迟刷
            bin log有类似的刷盘时机机制,同样由参数控制:不强制要求 / 每次提交都刷盘(默认) / 集齐N次提交后刷盘
        由于redo log采用循环写的方式记录下最近的操作,但要用到更久以前的操作来完成恢复时,就需要另一种日志对更久之前的操作归档
        这个日志就是bin log, 两者要配合使用才能保证当数据库发生宕机重启时,数据不会丢失
        MySQL提交时,分为两阶段提交,第一阶段提交时,执行器先写redo log(prepare),再写bin log,第二阶段提交时正式更新redo log(commit),保证两个日志数据的安全与同步
        bin log与redo log区别:
            redo log循环写,大小固定,会丢失;bin log追加写,大小通过配置参数决定,追加写到超过文件大小后会将后续日志记录到新的bin log不丢失
            redo log 适用于崩溃恢复,只有redo log是crush-safe的;binlog 除了配合崩溃恢复保证持久性之外,还适用于主从复制(也是重点)
            bin log所有引擎都支持,server层实现,redo log仅InnoDB支持,引擎层实现
            bin log支持三种记录方式(Statement / Row / Mixed),日志类型为逻辑日志;
            redo log日志类型为物理日志(物理日志用于恢复速度会快很多)
    一致性:
        bin log 也有类似的缓冲区,binlog刷盘时机同样是靠配置参数来控制
        可以选择不实时更新,牺牲一定的一致性来换取更好的性能,默认每次提交都刷盘(保证一致性)
    隔离性:
        事务隔离级别:            防脏读  防不可重复读  防幻读
            read uncommitted     X          X          X
            read committed       √          X          X
            repeatable read      √          √          X
            serializable         √          √          √
            脏读:读未提交
            不可重复读:同一事务两次读的结果不同(针对update)
            幻读:前后多次读取,数据总量不一致(针对insert、delete)
        MVCC:多版本并发控制,不同事务的读–写、写–读操作并发执行,从而提升系统性能
            读未提交:就全读最新的就是读未提交,不加任何判断
            读已提交和可重复读的实现:
                核心处理逻辑就是判断所有版本中哪个版本是当前事务可见的,称为 ReadView
                这个过程通过事务IDtrx_id来判断,这个ID严格递增
                读已提交:仅判断trx_id,在本次事务之前的都有效修改,可查
                可重复读:利用undo log,配合ReadView,当该事务执行相同读操作的时候,依据undo log恢复到开始时的数据,保证永远是第一次查询时的结果    
            串行化的实现:锁实现串行化,牺牲并发,保证ACID
    注意:以上三大日志都仅记录写入性操作,不包括查询操作(因为查询不更改数据库,也就没必要记录了)

2022-02-26 23:40 回复