MySql的行锁、表锁,select……for update到底是加了行锁,还是表锁?

行锁与表锁详解

一、定义与核心区别
  1. ​行锁(Row Lock)​

    • ​定义​​:锁定表中的单行数据,其他事务可操作表中其他行。
    • ​特点​​:锁粒度小、并发度高,但可能引发死锁
    • ​适用场景​​:高并发读写(如账户余额更新、订单处理)

  2. ​表锁(Table Lock)​

    • ​定义​​:锁定整张表,其他事务无法进行写操作。
    • ​特点​​:锁粒度大、并发度低,但实现简单且无死锁风险
    • ​适用场景​​:批量操作(如ALTER TABLE、全表更新)或低并发场景


二、触发条件
  1. ​行锁触发条件​

    • ​索引条件​​:查询或更新语句必须使用索引(主键或二级索引),否则退化为表锁

    • ​事务操作​​:在事务中对数据行执行SELECT ... FOR UPDATEUPDATE/DELETE语句

    • ​引擎限制​​:仅InnoDB引擎支持行锁,MyISAM仅支持表锁

    ​示例代码​​(行锁):

    -- 事务中通过主键加行锁
    BEGIN;
    SELECT * FROM users WHERE id = 1 FOR UPDATE; -- 行级排他锁
    UPDATE users SET balance = balance - 100 WHERE id = 1;
    COMMIT;
  2. ​表锁触发条件​

    • ​无索引操作​​:当WHERE条件未命中索引时,InnoDB自动升级为表锁

    • ​显式锁定​​:使用LOCK TABLES命令手动加锁

    • ​DDL操作​​:ALTER TABLE、TRUNCATE等结构变更操作自动加表锁

    ​示例代码​​(表锁):

    -- 显式锁定整张表
    LOCK TABLES users WRITE;
    -- 执行批量更新
    UPDATE users SET status = 'inactive' WHERE create_time < '2024-01-01';
    UNLOCK TABLES;

三、关键注意事项
  1. ​索引的重要性​

    • 若未使用索引,即使InnoDB引擎也会退化为表锁。例如:
      -- name字段无索引时,触发表锁
      UPDATE users SET balance = 0 WHERE name = 'Alice'; -- 全表扫描,表级锁[8,10](@ref)
  2. ​死锁风险​

    • 行锁可能因事务交叉等待导致死锁,需通过SHOW ENGINE INNODB STATUS分析
    • 优化建议:事务按固定顺序操作资源,减少锁持有时间

  3. ​锁类型与隔离级别​

    • 可重复读(RR)隔离级别下,InnoDB会使用间隙锁(Gap Lock)防止幻读
    • 示例:
      -- 间隙锁锁定范围(假设id=5不存在)
      SELECT * FROM products WHERE id BETWEEN 2 AND 6 FOR UPDATE; -- 锁定(2,6)区间[1,11](@ref)

四、总结对比
​特性​​行锁​​表锁​
​粒度​单行数据整张表
​并发性​高(仅阻塞冲突行)低(阻塞全表写操作)
​死锁风险​可能发生
​适用引擎​InnoDBMyISAM/InnoDB(无索引时退化)
​典型场景​高并发OLTP(如电商交易)批量操作/结构变更

​建议​​:

  • 优先使用InnoDB引擎并合理设计索引,避免无索引导致的表锁
  • 对高频写操作,通过缩小事务范围降低锁冲突概率

详细可参考

select...for update到底是加了行锁,还是表锁? - 苏三说技术 - 博客园

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值