要优化 InnoDB
事务处理,请在事务功能的性能开销和服务器工作负载之间找到理想的平衡点。例如,如果应用程序每秒提交数千次,则可能会遇到性能问题;如果每 2-3 小时才提交一次,则可能会遇到不同的性能问题。
默认的 MySQL 设置
AUTOCOMMIT=1
可能会对繁忙的数据库服务器造成性能限制。在可行的情况下,通过发出SET AUTOCOMMIT=0
或START TRANSACTION
语句,在进行所有更改后 followed by aCOMMIT
语句,将几个相关的数据更改操作包装到单个事务中。如果事务对数据库进行了修改,则
InnoDB
必须在每次事务提交时将日志刷新到磁盘。当每次更改后都进行提交时(使用默认的自动提交设置),存储设备的 I/O 吞吐量会限制每秒可能执行的操作数。或者,对于仅包含单个
SELECT
语句的事务,打开AUTOCOMMIT
有助于InnoDB
识别只读事务并对其进行优化。有关要求,请参阅 第 10.5.3 节 “优化 InnoDB 只读事务”。避免在插入、更新或删除大量行后执行回滚。如果一个大事务降低了服务器性能,则回滚可能会使问题变得更糟,执行回滚所需的时间可能是原始数据更改操作的数倍。终止数据库进程无济于事,因为回滚会在服务器启动时再次启动。
要尽量减少此问题发生的可能性,请执行以下操作
增加 缓冲池 的大小,以便可以缓存所有数据更改,而不是立即写入磁盘。
设置
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
可能需要使用聚簇索引查找记录。