让一个事务真实锁住接近全表96%的行,看锁的数量、内存占用,以及剩下没被命中的行是否真的完全不受影响。
orders表5万行,customer_id BETWEEN 1 AND 8000这个条件真实匹配了48023行(约96%)。
session KSTART TRANSACTION; SELECT COUNT(*) FROM orders WHERE customer_id BETWEEN 1 AND 8000 FOR UPDATE; SELECT SLEEP(5); COMMIT;
637 lock struct(s), heap size 90232, 48023 row lock(s)
InnoDB真实为这48023行分别维护了独立的记录锁,用637个锁结构(每个结构用位图压缩了同一个数据页上的多条记录锁)、总共真实只占用约90KB内存就存下了。这不是一把笼统的"这张表被锁住了"的粗粒度标记,而是真实精确到每一行的细粒度记录,可以通过performance_schema.data_locks逐条查出具体锁在了哪一行。
更新customer_id=100(真实在K的锁定范围1~8000内): ERROR 1205 (HY000): Lock wait timeout exceeded ← 真实被挡住 更新customer_id=19999(真实在K的锁定范围之外): 真实538微秒(约0.54毫秒)就完成了,同一张表,完全不等待
每一步都是本文上面用真实并发会话跑出来的原始结果。
performance_schema.data_locks + SHOW ENGINE INNODB STATUS:真实统计锁结构数量和内存占用