要优化 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_flush_log_at_trx_commit
参数设置为 0。InnoDB
仍然会尝试每秒刷新一次日志,尽管不能保证刷新。修改或删除行时,行和关联的 撤消日志 不会立即或甚至在事务提交后立即被物理删除。旧数据将保留到较早或并发启动的事务完成为止,以便这些事务可以访问修改或删除行的先前状态。因此,长时间运行的事务可能会阻止
InnoDB
清除由不同事务更改的数据。在长时间运行的事务中修改或删除行时,如果使用
READ COMMITTED
和REPEATABLE READ
隔离级别的其他事务读取相同的行,则它们必须做更多的工作来重建旧数据。当长时间运行的事务修改表时,来自其他事务的对该表的查询不会使用 覆盖索引 技术。通常可以从辅助索引中检索所有结果列的查询,改为从表数据中查找适当的值。
如果发现二级索引页的
PAGE_MAX_TRX_ID
太新,或者二级索引中的记录被标记为删除,InnoDB
可能需要使用聚簇索引查找记录。