10.5.2 优化InnoDB事务管理
为了优化InnoDB
的事务处理,找到性能开销与服务器负载之间的理想平衡。例如,如果应用程序每秒提交数千次事务,它可能会遇到性能问题,而如果它只在2-3小时后提交一次,则可能会遇到不同的性能问题。
-
MySQL的默认设置
AUTOCOMMIT=1
对于一个繁忙的数据库服务器可能会带来性能限制。在可能的情况下,将多个相关数据变更操作包装在单个事务中,通过发出SET AUTOCOMMIT=0
或START TRANSACTION
语句,然后在所有更改之后使用COMMIT
语句。InnoDB
必须将日志刷新到磁盘上每次事务提交时,如果该事务对数据库进行了修改。当每个变更都跟随一个提交(如默认自动提交设置)时,存储设备的I/O吞吐量会限制可能操作数每秒。 -
或者,对只包含单个
SELECT
语句的事务,打开AUTOCOMMIT
有助于InnoDB
识别只读事务并对其进行优化。请参阅第10.5.3节,“优化InnoDB只读事务”以获取要求。 -
避免在插入、更新或删除大量行之后进行回滚。若一个大事务拖慢了服务器性能,回滚可能会使问题更糟,潜在地比原始数据变更操作长好几倍。杀死数据库进程并不会帮助,因为启动服务器时回滚将再次开始。
为了最小化这种问题的发生:
-
增加
buffer pool
的大小,以便所有数据变更操作都可以缓存,而不是立即写入磁盘。 -
设置
innodb_change_buffering=all
,以便更新和删除操作也可以缓冲(除了插入之外)。 -
考虑在大数据变更操作期间定期发出
COMMIT
语句,可能将单个删除或更新操作分解为多个操作,每个操作只处理较少的行数。
一旦发生了逃逸的回滚,可以通过增加缓冲池大小,使回滚成为CPU密集型并快速运行,或杀死服务器并在重启时使用
innodb_force_recovery=3
,如第17.18.2节“InnoDB恢复”中所述。 -
-
如果您可以承受在意外退出时丢失最新提交的事务,您可以将
innodb_flush_log_at_trx_commit
参数设置为0。InnoDB
会尝试每秒刷新日志一次,尽管刷新不是保证的。 -
当行被修改或删除时,行及其相关的撤销日志不会立即物理移除,甚至在事务提交后也不是立即移除。旧数据会保留到开始或并发的事务完成之前,以便那些事务可以访问由不同事务修改或删除的行的前状态。因此,一次长时间运行的事务可以阻止
InnoDB
从清理由其他事务改变的数据。 -
当在一个长时间运行的事务中修改或删除行时,使用
READ COMMITTED
和REPEATABLE READ
隔离级别的事务必须做更多的工作来重建更旧的数据,如果它们读取了相同行。 -
当一个长时间运行的事务修改表时,从其他事务查询该表的查询不会利用覆盖索引技术。那些通常可以从次级索引中检索所有结果列的查询,实际上必须查找适当值的表数据。
如果次级索引页面上的PAGE_MAX_TRX_ID过于新,或者次级索引中的记录被删除标记,
InnoDB
可能需要通过聚簇索引来查找记录。