本机用一张id取值10,20,30...80的表验证:SELECT ... WHERE id BETWEEN 10 AND 30 FOR UPDATE真实锁住了(10,20)和(20,30)这两个间隙,向id=15插入真实被阻塞;但id=10前面和id=30后面的间隙没被锁,真实立即插入成功。
本机用两个查询真实做出对比:不匹配真实行的范围查询拿到的是纯Gap Lock,不会阻止更新边界记录;真实匹配到行的范围查询拿到的是Next-Key Lock,会阻止更新记录本身——同样落在id=20,是否匹配真实数据决定了锁的种类。
本机验证同一个空间隙里,两个会话真实并发插入不同的id,谁都没等谁,各自1.4毫秒左右完成;但如果第三个会话先真实拿到了这个间隙的Gap Lock,同样的插入就真实被挡住直到超时。
本机对比同一个被锁住的行,默认的FOR UPDATE真实等满3秒才报错,FOR UPDATE NOWAIT真实0.0138秒就报错返回——快了约217倍,而且是完全不同的错误码1205对3572。
本机制造了一个真实的经典死锁,InnoDB真实检测到后选一个回滚。把其中一边改成先改5行再冲突,真实测了3轮,改得少的那一边每次都真实被选中回滚,改得多的那一边每次都真实活下来。
本机一个事务真实锁住orders表里48023行,performance_schema.data_locks真实数出48023条独立的记录锁,只占用真实90232字节内存;同一张表里没被锁到的行真实0.5毫秒就被另一个会话改完了——没有锁升级成表锁。
本机验证一个开着REPEATABLE READ快照的长事务:另一个会话在它存活期间真实提交了一次更新,History list length真实从0变成了1;但真实测下来purge线程清零并不是长事务一提交就立刻发生的,如实记录了这个不确定的真实等待时间。
本机验证History list length真实有两个来源:SHOW ENGINE INNODB STATUS文本和information_schema.INNODB_METRICS官方计数器,真实同一时刻查两者完全一致;但连续多轮真实观测,涨跌的具体时机真实不完全可预测。
本机真实的InnoDB默认有2个undo tablespace,各占32MB磁盘;用CREATE UNDO TABLESPACE真实建了第3个,随后DROP UNDO TABLESPACE真实干净地删掉了它。真实测了500次并发小更新,undo文件大小完全没有变化——undo空间是预分配的循环区域。
本机验证ROLLBACK TO SAVEPOINT真实只撤销数据改动,不撤销锁:savepoint之后的改动被真实回滚,但真实测试发现回滚之后那一行依然被锁着,并发更新真实还是要排队超时,跟从未回滚过的行表现完全一样。
本机真实做了一次两阶段提交:PREPARE之后原连接真实关闭,从全新连接查询数据改动还没生效;用XA RECOVER真实在新连接里把这个悬而未决的事务找了出来,XA COMMIT之后改动才真实落地。
本机对同一个全表扫描测了两次:第一次因为表已被反复用过,命中率约95%;紧接着原样再扫一次,物理读真实一次都没增加——命中率100%。真实说明在共享开发库上很难量出真正冷启动的读。