行锁和表锁是 MySQL 中两种基础的并发控制机制,核心区别在于锁定范围不同:行锁只锁住满足条件的某几行数据,表锁则直接锁住整张表。
行锁:细粒度、高并发、依赖索引
行锁由 InnoDB 存储引擎实现,是 MySQL 最小粒度的锁。它只对 SQL 实际访问到的数据行加锁,其他事务仍可操作表中未被锁定的行。
自动触发:执行 UPDATE、DELETE、INSERT 时,InnoDB 默认对涉及的行加排他锁(X锁);普通 SELECT 不加锁 显式使用:SELECT ... FOR UPDATE 加排他锁,SELECT ... LOCK IN SHARE MODE 加共享锁(S锁) 关键前提:必须走索引(主键或二级索引),否则会退化为表锁——比如WHERE name = 'xxx'若
name无索引,就会锁全表 优点:并发高、冲突少;缺点:开销大、可能死锁、需合理设计索引
表锁:粗粒度、简单快、适合批量操作
表锁作用于整张表,MyISAM 引擎默认使用表锁,InnoDB 在特定场景下也会用(如显式
LOCK TABLES或 DDL 操作)。 自动加锁:MyISAM 执行 SELECT 自动加读锁(共享锁),执行 UPDATE/INSERT/DELETE 自动加写锁(独占锁) 显式加锁:
LOCK TABLES t1 READ(允许多个读)、
LOCK TABLES t1 WRITE(仅当前会话可读写) 读锁不阻塞读,但阻塞写;写锁阻塞所有读写;MyISAM 写操作是串行的 优点:开销小、不会死锁;缺点:并发低、容易成为性能瓶颈
怎么选?看业务场景和引擎
绝大多数在线业务应优先用 InnoDB + 行锁,尤其订单、库存、账户等高频更新场景。表锁更适合临时批量导入、统计报表生成、或 MyISAM 只读查询为主的系统。
注意:InnoDB 的行锁能力不是“自动生效”的——没有索引的 WHERE 条件、全表扫描、或使用
LIKE '%abc'等无法命中索引的情况,都会导致锁升级为表锁。
