8.5.3-优化InnoDB只读事务

InnoDB可以避免为只读事务设置事务id(TRX_ID字段)的开销。只有在可能执行写操作或锁定读(比如select … for update)时,才需要事务id。消除不必要的事务id可以减少查询或数据变更构造视图时的内部数据结构大小。

以下情形,InnoDB可以检测到只读事务:

  • 使用START TRANSACTION READ ONLY语句启动的事务。这种场景下,尝试去修改数据会报错(对于InnoDB,MyISAM,或其它类型的表),且事务会以只读状态继续:
ERROR 1792 (25006): Cannot execute statement in a READ ONLY transaction.

在只读事务中,你仍然可以修改会话级别的临时表,或者对齐进行锁定查询。因为,这些变更和锁对其它事务不可见。

  • autocommit设置被打开,因此事务就是单语句的,且事务中的这个 单语句 是一条 “非锁定”的SELECT语句。意思是说,这是一条不带FOR UPDATELOCK IN SHARE MODESELECT语句。
  • 启动事务的时候不带READ ONLY选项,但是没有执行UPDATE或显式锁定记录的语句。在更新或需要显式锁定之前,事务都是只读状态。

因此,对于读密集型应用(比如报告生成器),你可以调整查询语句序列,将其分组分配到带READ ONLY选项的事务中,或是在执行SELECT语句前打开autocommit开关,或是简单的不在这些查询中间插入数据变更语句。 想了解关于start transaction和autocommit的信息,请查阅章节 13.3.1,“START TRANSACTION, COMMIT, and ROLLBACK Statements”

符合自动提交,非锁定,以及只读(AC-NLRO)的事务,被排除在一些InnoDB数据结构之外,所以使用show engine innodb statu时,输出中没有这些事务。