s锁和x锁不能共存,因为s锁仅允许读、x锁需写入,若同时存在会导致脏读或更新丢失;s锁之间兼容以支持并发读,且同一事务内重复加s锁可复用,而跨事务时x锁申请会被已持s锁的事务阻塞。

为什么S锁和X锁不能共存
因为S锁只允许读,X锁要写,一旦允许同时存在,就可能出现脏读或更新丢失。比如事务A用SELECT ... LOCK IN SHARE MODE加了S锁,事务B却能用UPDATE加X锁修改同一行——这直接破坏了隔离性。所以只要有一方持S锁,另一方申请X锁就会被阻塞;反之亦然。
同一行上S+S为什么能成功
多个事务同时读同一行不改变数据,没必要互斥。InnoDB允许它们各自获得S锁,这是并发读的基石。但注意:这个“兼容”仅限于同一行记录上的S锁之间;如果事务A对id=1加了S锁,事务B对id=2加S锁,那是两把独立的锁,根本不在一个冲突域里,谈不上兼容与否。
为什么同一个事务内重复加S锁不会报错
锁是按事务粒度管理的,不是语句级。同一个事务中执行两次SELECT ... LOCK IN SHARE MODE,第二次不会触发兼容性检查——InnoDB知道这是自己持有的锁,直接复用。但跨事务就不行:事务A持S锁未释放时,事务B再申请S锁可以,申请X锁则必然等待。
实际排查时最常忽略的一点
你看到的“锁冲突”,往往不是S/X直接打架,而是背后隐含的意向锁(IX/IS)在拦路。比如事务A执行SELECT ... FOR UPDATE,先在表上加IX锁,此时另一个事务想对整张表加S锁(如LOCK TABLES t READ),就会因IX与S冲突而失败——但错误日志里可能只显示“Waiting for table level lock”,根本没提IX。这种间接阻塞最容易被误判为SQL写法问题。











