• MySQL加锁分析 (转)


    参考:MySQL 加锁处理分析。该文已经讲的很详尽了,也易懂,下面仅仅是个人做的总结。

    一、 背景

    1.1 隔离级别

    1.2 加锁过程

      逐条处理,逐条加锁。

    update 执行流程

    1.3 两阶段锁2PL

    1.4 gap锁

      gap锁是间隙锁,即相邻两条有效记录间隙的锁(锁的是间隙),它是针对insert的,用来解决幻读的发生。它会阻塞insert,但不会阻塞delete/update等(记录本来也不存在)。

      RC与RR的重要区别就是幻读。所以RR才需要引入gap锁。

    二、加锁组合分析

      说加什么锁,首先要了解两个前提:1)隔离级别;2)用到的索引。不同的隔离级别,不同的索引都会影响加锁。

    2.1 可提交读RC

      主键/唯一键 二级索引 无索引
    select
    insert 行锁 行锁 行锁
    select...for update/update/delete 行锁 有效行的行锁 全表锁聚簇索引

    2.2 可重复读RR

      主键/唯一键 二级索引 无索引
    select
    insert 行锁 行锁 行锁
    select...for update/update/delete 行锁 有效行的行锁+gap锁 全表锁聚簇索引

    2.3 可序列化S

      主键/唯一键 二级索引 无索引
    select(快照读) S S S
    其他(当前读) X X X

      注意:无索引时,select...for update/update/delete是需要锁全表的,但mysql_server可以做优化,在逐条加锁时,如果发现不是目标记录,可以释放掉锁。但这会违背2PL的原则。

    2.4 结论

      死锁的发生与否,并不在于事务中有多少条SQL语句,死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

      加锁过程是逐条处理,逐条加锁(最终都反映在聚簇索引上)的。

    • 主键,加在聚簇索引上;
    • 二级索引,加在二级索引+聚簇索引上;
    • 无索引,加在聚簇索引上。

    所以如果两个session用到不同的二级索引,那么对聚簇索引的加锁顺序是不一致的,从而导致session间锁的持有与竞争,很容易产生死锁。

    • 作者:水岩
    • 出处:http://www.cnblogs.com/waterystone
    • 本博客中未标明转载的文章归作者水岩和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    LeetCode "Palindrome Partition II"
    LeetCode "Longest Substring Without Repeating Characters"
    LeetCode "Wildcard Matching"
    LeetCode "Best Time to Buy and Sell Stock II"
    LeetCodeEPI "Best Time to Buy and Sell Stock"
    LeetCode "Substring with Concatenation of All Words"
    LeetCode "Word Break II"
    LeetCode "Word Break"
    Some thoughts..
    LeetCode "Longest Valid Parentheses"
  • 原文地址:https://www.cnblogs.com/zping/p/10996360.html
Copyright © 2020-2023  润新知