Mysql行锁、表锁和间隙锁区别

举报
一颗小谷粒 发表于 2025/07/31 18:52:56 2025/07/31
【摘要】 Mysql行锁、表锁和间隙锁区别以下是MySQL行锁、表锁和间隙锁的详细解析及案例分析,结合核心机制与实战场景进行说明:🔐 一、锁类型详解1. 行锁(Row Lock)机制锁定数据表中的单行记录,是InnoDB引擎的默认锁机制。共享锁(S锁)允许多个事务并发读取同一行,但阻止任何写操作。SELECT*FROM users WHERE id =1 LOCK IN SHARE MODE;排他锁...

Mysql行锁、表锁和间隙锁区别


以下是MySQL行锁、表锁和间隙锁的详细解析及案例分析,结合核心机制与实战场景进行说明:


🔐 一、锁类型详解

1. 行锁(Row Lock)

  • 机制
    锁定数据表中的单行记录,是InnoDB引擎的默认锁机制。
    • 共享锁(S锁)
      允许多个事务并发读取同一行,但阻止任何写操作。
      SELECT*FROM users WHERE id =1 LOCK IN SHARE MODE;
    • 排他锁(X锁)
      仅允许持有锁的事务读写数据,其他事务无法加锁或读写。
      UPDATE users SET balance =100WHERE id =1-- 自动加X锁
  • 触发条件
    需通过索引定位数据行。若WHERE条件无索引,行锁退化为表锁(如UPDATE users SET status=1 WHERE name='Alice',若name无索引)。
  • 案例:
    转账场景中,事务A锁定账户1,事务B锁定账户2,互相等待对方释放锁时形成死锁:
    -- 事务A
    UPDATE accounts SET balance = balance -100WHERE id =1;
    UPDATE accounts SET balance = balance +100WHERE id =2-- 等待事务B释放id=2的锁

    -- 事务B
    UPDATE accounts SET balance = balance -100WHERE id =2;
    UPDATE accounts SET balance = balance +100WHERE id =1-- 等待事务A释放id=1的锁
    解决:按固定顺序访问资源(如先操作id小的账户)。

2. 表锁(Table Lock)

  • 机制
    锁定整张表,MyISAM引擎默认支持,InnoDB在特定场景下使用。
    • 读锁(S锁)
      允许多事务并发读,但阻塞所有写操作。
    • 写锁(X锁)
      仅允许持有锁的事务读写,其他事务完全阻塞。
  • 触发条件:
    • 显式命令:LOCK TABLES users WRITE;
    • 隐式升级:无索引的全表扫描(如UPDATE users SET status=0)、DDL操作(如ALTER TABLE)。
  • 案例:
    库存表批量更新时,若未通过索引筛选,全表锁定导致并发写入阻塞:
    UPDATE products SET stock = stock -10-- 无WHERE条件,触发表锁
    优化:添加索引+分批更新(如WHERE id BETWEEN 1 AND 1000)。

3. 间隙锁(Gap Lock)

  • 机制
    锁定索引记录之间的间隙(如id=5id=10的空区间),防止其他事务插入数据,解决“幻读”。
  • 触发条件:
    • 可重复读(RR) 隔离级别下使用范围查询或非唯一索引。
    • 例如:SELECT * FROM users WHERE age BETWEEN 20 AND 30 FOR UPDATE; 锁定age在20~30之间的所有间隙。
  • 案例:
    事务A查询年龄在20-30岁的用户并加锁,事务B尝试插入年龄25的新用户被阻塞:
    -- 事务A
    SELECT*FROM users WHERE age BETWEEN20AND30FORUPDATE-- 锁定(20,30)的间隙

    -- 事务B(被阻塞)
    INSERTINTO users (name, age) VALUES ('Bob'25);
    规避:使用唯一索引精确查询(如WHERE id=5),或降级隔离级别至读已提交(RC)

⚠️ 二、锁冲突与死锁

锁兼容性矩阵

当前锁状态 \ 请求锁
共享锁 (S)
排他锁 (X)
间隙锁 (Gap)
共享锁 (S)
排他锁 (X)
间隙锁 (Gap)

说明:S锁兼容其他读操作,X锁与所有锁冲突,间隙锁仅兼容其他间隙锁。

死锁成因与解决

  • 成因
    事务循环等待资源(如A持X锁等B,B持X锁等A)。
  • 解决方案:
    1. 设置超时
      SET innodb_lock_wait_timeout = 5;(默认50秒)。
    2. 死锁检测
      启用innodb_deadlock_detect=ON自动回滚代价小的事务。
    3. 业务优化
      按固定顺序访问资源(如所有事务先操作id小的行)。

🔧 三、优化策略与监控

  1. 索引优化

    • 确保WHERE条件使用索引,避免行锁升级为表锁。
    • 示例:为products表的category_id加索引,缩小锁定范围。
  2. 事务设计

    • 避免长事务:减少锁持有时间(如拆分大事务)。
    • 使用乐观锁:通过版本号减少锁竞争(如UPDATE ... WHERE version=old_version)。
  3. 隔离级别调整

    • 读已提交(RC):避免间隙锁,但可能幻读;可重复读(RR):需权衡一致性与并发。
  4. 锁监控工具

    • 实时查看锁等待:
      SELECT*FROM information_schema.INNODB_LOCKS; 
      SELECT*FROM information_schema.INNODB_LOCK_WAITS;
    • 分析死锁日志:SHOW ENGINE INNODB STATUS;

💎 四、总结

  • 行锁
    高并发场景首选,需索引支持防升级。
  • 表锁
    简单但并发低,慎用于写频繁场景。
  • 间隙锁
    RR隔离级别防幻读的核心,但易引发阻塞。
    优化铁律索引精准锁范围,事务短小避冲突,监控死锁早干预
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。