默认情况下MySQL多线程同时UPDATE同一行时后到请求被阻塞等待而非报错由InnoDB行级锁与next-key lock机制保证顺序执行WHERE条件未走索引会导致全表扫描并逐行加锁引发严重性能下降。MySQL 更新同一行时会卡住还是报错默认情况下多线程同时执行 UPDATE 同一行后到的请求不会报错而是被阻塞等待——直到前一个事务提交或回滚释放锁。这是 InnoDB 的行级锁 next-key lock 在起作用不是“谁快谁赢”而是“谁先拿到锁谁先执行”。常见错误现象– 应用日志里突然出现大量 Lock wait timeout exceeded– 某条 UPDATE 执行时间从几毫秒飙到 50 秒以上– SHOW PROCESSLIST 里看到状态长期卡在 Updating 或 Waiting for table metadata lock注意后者通常是 DDL 导致不是行锁实操建议– 用 SELECT ... FOR UPDATE 显式加锁前确认业务是否真需要强一致性多数场景用 UPDATE ... WHERE 带条件唯一索引就能安全并发– 检查是否无意中触发了间隙锁比如 WHERE id 100 但没走索引导致锁住一片范围– 避免在事务里混用 SELECT 和 UPDATE尤其跨表时容易扩大锁范围UPDATE 语句没走索引会导致全表锁吗不会全表锁但可能锁住远超预期的行数。InnoDB 只能对索引记录加行锁如果 UPDATE 的 WHERE 条件没命中索引它会扫描全表或全索引对**每一条扫描到的记录都尝试加锁**——实际效果接近“伪全表锁”并发性能断崖下跌。使用场景– 日常运营后台批量修正数据WHERE status pending 却没给 status 加索引– 临时脚本直接 UPDATE users SET name ? WHERE created_at 而 codecreated_at 无索引实操建议– 执行前一定看 EXPLAIN UPDATE ...MySQL 8.0.19 支持低版本可用 EXPLAIN SELECT 模拟– 如果必须扫全表考虑分批更新UPDATE ... WHERE id BETWEEN ? AND ?配合主键切片– 别依赖 FORCE INDEX 强行走索引——如果索引区分度极低比如性别字段优化器不选它反而是对的REPEATABLE READ 隔离级别下更新会幻读吗不会产生幻读更新但可能因 gap lock 导致“看似幻读”的阻塞。比如事务 A 执行 UPDATE orders SET status shipped WHERE user_id 123 AND status paid此时事务 B 插入一条 user_id 123, status paid 的新订单——B 会被阻塞直到 A 提交。这不是幻读幻读指 SELECT 多出记录而是 gap lock 主动拦住了插入。 通义听悟 阿里云通义听悟是聚焦音视频内容的工作学习AI助手依托大模型帮助用户记录、整理和分析音视频内容体验用大模型做音视频笔记、整理会议记录。