要优化 InnoDB
事务处理,找到事务功能的性能开销和服务器工作负载之间的理想平衡。例如,应用程序可能会遇到性能问题,如果它每秒提交数千次,并且在每2-3小时提交一次时遇到不同的性能问题。
-
默认的 MySQL 设置
AUTOCOMMIT=1
可能会对繁忙的数据库服务器施加性能限制。在可能的情况下,将几个相关的数据更改操作包装到单个事务中,通过发出SET AUTOCOMMIT=0
或START TRANSACTION
语句,后跟一个COMMIT
语句,以便进行所有更改。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_change_buffering=all
时应该很少出现,该设置允许更新和删除操作被缓存在内存中,使它们变得更快,并且在需要时也更快地回滚。确保在处理长时间事务的服务器上使用这个参数设置,包括许多插入、更新或删除操作。 -
-
如果您可以承担一些最新提交的事务在意外退出时的损失,可以将
innodb_flush_log_at_trx_commit
参数设置为 0。InnoDB
尝试每秒刷新日志一次,尽管不能保证刷新。 -
当行被修改或删除时,相关的 撤销日志 不会立即被物理删除,甚至在事务提交后也不会。旧数据将被保留,直到早期或同时启动的事务完成,以便这些事务可以访问修改或删除行的先前状态。因此,长时间事务可能会阻止
InnoDB
清除由不同事务修改的数据。 -
当行在长时间事务中被修改或删除时,使用
READ COMMITTED
和REPEATABLE READ
隔离级别的其他事务需要更多工作来重建旧数据,如果它们读取了相同的行。 -
当长时间运行的事务修改表时,从其他事务对该表的查询不会使用覆盖索引技术。通常可以从辅助索引中检索所有结果列的查询,反之会从表数据中查找适当的值。
如果辅助索引页的
PAGE_MAX_TRX_ID
太新,或者辅助索引中的记录被删除标记,InnoDB
可能需要使用聚簇索引来查找记录。