### 15.6.6 撤消日志

撤消日志是与单个读写事务关联的撤消日志记录的集合。撤消日志记录包含有关如何撤消事务对[聚集索引](glossary.html#glos_clustered_index)记录。如果另一个事务需要将原始数据视为一致读取操作的一部分，则从撤消日志记录中检索未修改的数据。撤消日志存在于[撤消日志段](glossary.html#glos_undo_log_segment), 包含在[回滚段](glossary.html#glos_rollback_segment).回滚段驻留在[撤消表空间](glossary.html#glos_undo_tablespace)并且在[全局临时表空间](glossary.html#glos_global_temporary_tablespace).

驻留在全局临时表空间中的撤消日志用于修改用户定义的临时表中的数据的事务。这些撤消日志不是重做日志，因为它们不是崩溃恢复所必需的。它们仅用于服务器运行时的回滚。这种类型的撤消日志通过避免重做日志记录 I/O 来提高性能。

有关撤消日志的静态数据加密的信息，请参阅[撤消日志加密](innodb-data-encryption.html#innodb-data-encryption-undo-log).

每个 undo 表空间和全局临时表空间分别支持最多 128 个回滚段。这[`innodb_rollback_segments`](innodb-parameters.html#sysvar_innodb_rollback_segments)变量定义回滚段的数量。

回滚段支持的事务数取决于回滚段中的撤消槽数和每个事务所需的撤消日志数。回滚段中的撤消槽数根据不同而有所不同`InnoDB`页面大小。

| InnoDB 页面大小 | 回滚段中的撤消槽数（InnoDB 页面大小 / 16） |
| ----------- | --------------------------- |
| `4096 (4KB)` | `256` |
| `8192 (8KB)` | `512` |
| `16384 (16KB)` | `1024` |
| `32768 (32KB)` | `2048` |
| `65536 (64KB)` | `4096` |

一个事务最多被分配四个撤消日志，一个用于以下操作类型中的每一种：

1.  [`插入`](insert.html)对用户定义表的操作

2.  [`更新`](update.html)和[`删除`](delete.html)对用户定义表的操作

3.  [`插入`](insert.html)对用户定义的临时表的操作

4.  [`更新`](update.html)和[`删除`](delete.html)对用户定义的临时表的操作

    根据需要分配撤消日志。例如，执行的事务[`插入`](insert.html),[`更新`](update.html)， 和[`删除`](delete.html)对常规表和临时表的操作需要完整分配四个撤消日志。只执行的事务[`插入`](insert.html)常规表上的操作需要单个撤消日志。

    对常规表执行操作的事务从分配的撤消表空间回滚段分配撤消日志。对临时表执行操作的事务从分配的全局临时表空间回滚段分配撤消日志。

    分配给事务的撤消日志在其持续时间内保持附加到事务。例如，分配给事务的撤消日志[`插入`](insert.html)常规表上的操作用于所有[`插入`](insert.html)该事务对常规表执行的操作。

    鉴于上述因素，以下公式可用于估计并发读写事务的数量`InnoDB`有能力支撑。

笔记

在达到并发读写事务数之前，可能会遇到并发事务限制错误`InnoDB`有能力支撑。当分配给事务的回滚段用完撤消槽时，就会发生这种情况。在这种情况下，请尝试重新运行事务。

事务对临时表执行操作时，并发读写事务的数量`InnoDB`能够支持受分配给全局临时表空间的回滚段数的限制，默认情况下为 128。

-   如果每笔交易都执行[`插入`](insert.html) **要么**一个[`更新`](update.html)要么[`删除`](delete.html)操作，并发读写事务的数量`InnoDB`能够支持的是：

    ```
    (innodb_page_size / 16) * innodb_rollback_segments * number of undo tablespaces
    ```

-   如果每笔交易都执行[`插入`](insert.html) **和**一个[`更新`](update.html)要么[`删除`](delete.html)操作，并发读写事务的数量`InnoDB`能够支持的是：

    ```
    (innodb_page_size / 16 / 2) * innodb_rollback_segments * number of undo tablespaces
    ```

-   如果每笔交易都执行[`插入`](insert.html)对临时表的操作，并发读写事务的数量`InnoDB`能够支持的是：

    ```
    (innodb_page_size / 16) * innodb_rollback_segments
    ```

-   如果每笔交易都执行[`插入`](insert.html) **和**一个[`更新`](update.html)要么[`删除`](delete.html)对临时表的操作，并发读写事务的数量`InnoDB`能够支持的是：

    ```
    (innodb_page_size / 16 / 2) * innodb_rollback_segments
    ```
