当执行 SQL语句删除行时,InnoDB不会立即从数据库中物理删除。 仅当InnoDB 丢弃 为删除而编写的undo log 时,才会物理删除行及其索引记录(删除对应数据文件中的记录和索引)。
这种仅发生在不再需要多版本并发控制(MVCC)或回滚之后的删除操作,称为purge。
purge 操作用于清理历史的UNDO 日志页, UNDO 日志可以使事务回滚和保证一致性读(取决于事务隔离级别)。
(History list length)UNDO日志页面的数量通常很小,但是大量更新操作或长时间运行的事务(即使纯粹读取事务)也会导致(History list length)undo 日志的增加。长时间运行的只读事务也会导致(History list length)undo 页数量的增长,原因是在REPEATABLE READ和SERIALIZATION事务隔离级别中事务要求它们返回与读取快照相同的结果。因此,InnoDB的多版本并发控制(MVCC)需要保留旧数据的副本,直到所有依赖于它的事务(transactions)完成为止。这些都是通过UNDO日志完成的。
(History list length)的查看在后面。
两个例子:
- 在大型数据库中,在执行DML操作时,同时使用mysqldump 加 --single-transaction
- 使用autocommit = 0 时,执行SELECT而忘记进行显式的COMMIT或ROLLBACK,此时事务并没有结束
purge 操作在后台进行。在MySQL 5.6和更高版本中,这是使用一个或多个专用线程完成的。 (在MySQL 5.5中,您可以选择使用InnoDB主线程还是专用线程,在早期版本中始终使用InnoDB主线程。)配置的线程数(innodb_purge_threads)是允许的最大线程数,并且清除进程将根据需要自动调整线程数。
purge 进程基本上是一个循环,一直在寻找要清除的UNDO页面。并且以innodb_purge_batch_size 定义的大小(UNDO日志页数)的来清除。
- innodb_purge_threads
Property | Value |
---|---|
Property | Value |
Command-Line Format | --innodb-purge-threads=# |
System Variable | innodb_purge_threads |
Scope | Global |
Dynamic | No |
Type | Integer |
Default Value | 4 |
Minimum Value | 1 |
Maximum Value | 32 |
增加purge_threads 的数量,可以提升多表DML 的效率
- innodb_purge_batch_size
Property | Value |
---|---|
Command-Line Format | --innodb-purge-batch-size=# |
System Variable | innodb_purge_batch_size |
Scope | Global |
Dynamic | Yes |
Type | Integer |
Default Value | 300 |
Minimum Value | 1 |
Maximum Value | 5000 |
在多线程清除配置中,每个purge 线程处理undo 页的数量:innodb_purge_batch_size/innodb_purge_threads
innodb_purge_batch_size 限定了 每执行128次迭代后清除undo log 后,undo log page的数量。
innodb_purge_batch_size 与innodb_purge_threads 一起设置用于性能优化。 大多数情况下使用innodb_purge_batch_size默认值就可以了。
- innodb_max_purge_lag
当purge 滞后时间超过innodb_max_purge_lag 阈值时,将对INSERT,UPDATE 和 DELETE 操作施加延迟,以使purge 操作有时间赶上DML 操作。
默认值为0,表示没有最大 purge 滞后也有延迟。
通过 SHOW ENGINE INNODB STATUS
,可以查看 History list length
的值
------------
TRANSACTIONS
------------
Trx id counter 4874778630
Purge done for trx‘s n:o < 4874778624 undo n:o < 0 state: running but idle
History list length 24
参考 https://dev.mysql.com/doc/refman/5.7/en/innodb-purge-configuration.html