深入理解数据库ACID(MySQL)

 

ACID,是用来声明数据库事务的四大特性,即原子性 (Atomicity)、 一致性(Consistency)、隔离性(Isolation) 和 持久性(Durability).

原子性:
    既然谈到原子性,首先确定的是数据库引擎和事务已经开始了,在工作中事务一般是一组操作的集合,而原子性想要表达的就是集合中的元素在数据库当前事务中要么全部执行成功commit,要不全部失败rollback.

    如何实现原子性:undo log 回滚日志

    eg:数据库遇到不可抗力,导致事务执行失败,那怎么回滚呢?就是靠 undo log.
    
       select:select不需要有 undo log 对结果不影响.
       update:要记录原有更新列信息,方便回滚.
       insert: 记录主键即可,回滚直接删除.
       delete: 记录全部信息,回滚在插入,这也是为啥一般数据库都有 delete_flag.
    
    undo log 日志结构 因为undo log 要根据事务trx_id去查找
    
    ---------------------------------------------------------------
    |end of record|undo type|......|undo no|trx_id|start of record|
    ---------------------------------------------------------------
    
    end of record:     下一条undo日志的位置
    undo type:          日志类型
    undo no:             日志编号,一个事务中,日志编号从0开始,事务中的每个日志都会递增 +1
    trx_id:                  旧记录的trx_id值
    start of record:    上一条undo日志的位置
    
    大概示意,并不全,感兴趣的同学可以去深入学习.
    
    再说下 redo log (重做日志) 和 binlog(逻辑备份日志 主从同步)
    
    redo log 有一点不同,它有两种状态 prepare commit .
    redo log -> binlog 如果在写完redo log 之后服务器宕机,就很尴尬(主从数据不一致) 所以引入两阶段提交
    redolog 写完之后状态为 prepare 写 binlog 然后提交事务(更新内存页,然后更改redolog状态为commit 然后事务结束)
    如果在这之前重启了服务器 则会检查 prepare状态 的redolog 是否有 binlog 来补充逻辑,没有则删除 redolog.
    
    以上说的日志都是要落盘的,不然宕机数据就没了.
    
隔离性:

    读未提交(RU)        一个事务还没提交时,它做的变更就能被别的事务看到.
    读提交    (RC)        一个事务提交(commit)之后,它做的变更才会被其他事务看到.
    可重复读(RR)
    串行化    (S)
    
    并发处理多个DML更新操作时,出现多个事务处理同一条数据时,让事务有序进行,保证数据和事务的相对隔离.

    默认是RR 但一般生产环境都是RC 因为RC没有间隙锁
    (间隙锁的主要目的,就是为了防止其他事务在间隔中插入数据,导致“不可重复读”.而且间隙锁会导致死锁,innodb会检测死锁并解决)
    
    --------------------------------------------------------------
    |事务隔离级别                    |脏读    |不可重复读|    幻读|
    --------------------------------------------------------------
    |读未提交(read uncommitted)    |是        |    是        |是        |
    --------------------------------------------------------------
    |读提交(read committed)        |否        |    是        |是        |
    --------------------------------------------------------------
    |可重复读(repeatable read)    |否        |    否        |是        |
    --------------------------------------------------------------
    |串行化(serializable)            |否        |    否        |否        |
    --------------------------------------------------------------
    
    脏读 幻读 不可重复读 理解 和 解决方案
    
    脏读:            
        事务A读取了事务B未提交的数据,但是事务B回滚了,导致事务A读取了脏数据,解决很简单因为脏读存在于RU,所以用RC即可.


    幻读:            
        事务A多次读取某些数据,事务B新增或删除了数据,导致幻读.


    不可重复读:    
        事务A多次读取某些数据,事务B修改/删除 了数据,导致不可重复读.
        
    不可重复读注重修改,幻读注重删除或新增.    
    
    *RC隔离级别使用则需要注意不可重复读和幻读*
    
    mvcc 解决不可重复读 当前读即可解决 (不可修改和删除 锁住即可 根据隔离性其他事务会排队)
    
    解决幻读
    幻读产生原因:主要原因是快照读和当前读混合使用(for update,lock in share mode,update,delete都属于当前读)
    
    1.rc隔离级别 都用当前读(但不支持间隙 只支持单一业务主键的更改)  不能完全解决幻读问题
    2.rr隔离级别+当前读
    3.提升至串行化

持久性:
    
    先说下IO,肯定是缓冲区了,InnoDB 提供了 Buffer Pool
    
    读数据:会首先从缓冲池中读取,如果缓冲池中没有,则从磁盘读取在放入缓冲池;
    写数据:会首先写入缓冲池,缓冲池中的数据会定期同步到磁盘中;
    
    如宕机通过 redolog 和 binlog 实现持久化
    
一致性:

    通过原子性和持久性和隔离性共同完成数据库 一组数据从一个一致性状态到达另外一个一致性状态.
    
    **mvcc下一次讲**

posted @   苏子墨  阅读(157)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示