MySQL|8分钟带你深入了解MySQL是如何利用索引的,网友:大师,我悟了( 三 )


  • read committed: 一个事务提交commit后的修改才对另一个事务可见 。 但是可能会出现不可重复读的问题 , 即在一个事务1中 , 连续select两次 , 得到的结果不同 , 因为在这中间 , 可能记录被别的事务修改了 。
  • repeatable read:一个事务中 , 多次select的结果总是相同的 , 但可能出现幻读的情况 , 即虽然对于同一行的结果 , 始终是相同的 , 但可能别的事务在insert别的行 , 导致一个事务中间看到的记录是不同的 。
  • serializable:事务串行执行 。
  • 怎么解决不可重复读问题?在一个事务开始时 , 对涉及到的row加上行锁即可以保证另一个事务无法修改这一行 。 但是这解不了幻读的问题 , 因为别的事务可能insert的是别的行 。 这时候 , 需要引入gap lock 。 不仅锁这一个row , 还锁这个row的前后间隙 。
    具体怎么锁 , 根据查询条件是走唯一索引还是非唯一索引 , 是走等值匹配还是范围匹配有不同的gap lock lock的范围 , 但一个原则就是:保证你这个语句的查询范围内的数据不会被其他事务insert进去 。
    事务的两段锁:
    在事务的执行过程中 , 随时可以进行锁定 , 但只有事务执行完毕commit或者rollBack的时候 , 才会释放锁 。
    MVCC 多版本并发控制前面说锁分为读锁和写锁 , 这是一种悲观锁 , MVCC是一种乐观锁 , 通过版本号控制 , 读副本的方式 , 来使得select读不用加锁 , 每次都读副本 , 同时保证读到的都是事务开始之前写入的数据 。
    因为大多数数据库操作都是读多写少的 , 通过MVCC , 读操作不用加锁 , 减少了锁冲突的概率 , 提高吞吐 。 select和事务又有啥关系呢?对于mysql , 默认是auto-commit模式 , 如果不显示地开启一个事务 , 每个查询都被当作一个事务来执行 。
    mvcc怎么实现的
    • 每条记录后面增加两个version , 创建version和删除version 。
    • 对于select语句 , 只筛选那些创建version小于等于事务version(保证查询到的记录在当前事务开始之前就已经存在了) , 且删除version在当前version之后的(保证记录在当前事务开始的时候 , 未被删除) 。
    • insert 语句:插入新一行 , 创建version等于当前事务version 。
    • update语句:新插入一行 , 创建version等于当前事务version , 之前行的删除version设置为当前事务version 。
    • delete语句: 当前行的删除version设置为当前事务version 。
    快照读和当前读
    select语句读的是快照 , 通过读快照 , 在RR级别也不会有幻读 , 对于select for update这种当前读 , 通过next-key lock解决幻读问题 。
    今日份分享已结束 , 请大家多多包涵和指点!