Este artículo lo lleva a comprender el registro de deshacer de MySQL

1. La necesidad de revertir las transacciones

Cuando aprendimos sobre los asuntos antes, dijimos que los asuntos deben estar garantizados 原子性, es decir 事务中的操作要么全做,要么全不做. Pero a veces habrá algunas situaciones en la transacción, tales como:

  • 情况一:Se pueden encontrar varios errores durante la ejecución de la transacción, como errores en el propio servidor, errores del sistema operativo o incluso errores causados ​​por cortes repentinos de energía.
  • Caso 2: los programadores pueden ingresar declaraciones manualmente durante la ejecución de la transacción ROLLBACKpara finalizar la ejecución de la transacción actual

Las dos situaciones anteriores harán que la transacción finalice a la mitad de la ejecución, pero es posible que se hayan modificado muchas cosas durante el proceso de ejecución de la transacción. Para garantizar la transacción, debemos volver a cambiar las cosas al estado original. Este proceso se 原子性llama 回滚(nombre en inglés: rollback), esto puede crear una falsa impresión: esta transacción no parece hacer nada, por lo que cumple con los requisitos de atomicidad.

Es como jugar a las cartas con nuestros amigos cuando éramos jóvenes. La carta de arrepentimiento es una operación de retroceso muy típica, por ejemplo, si juegas dos cartas de tres, la operación correspondiente a la carta de arrepentimiento es sacar las dos cartas de tres. La reversión en la base de datos es similar a la tarjeta de arrepentimiento, inserta un registro y la operación de reversión corresponde a la eliminación de este registro, actualiza un registro y la operación de reversión corresponde a la actualización del registro al valor anterior, si un registro se elimina, la operación de reversión corresponde a insertar el registro nuevamente. parece tan simple

A partir de la descripción anterior, ya podemos sentir vagamente que siempre que queramos realizar cambios en un registro (los cambios aquí pueden referirse a INSERT, DELETE, UPDATE), debemos anotar a mano todo lo necesario para la reversión. Por ejemplo:

  • Cuando inserta un registro, debe al menos escribir el valor de la clave principal de este registro, y luego, cuando revierte, solo necesita eliminar el registro correspondiente al valor de la clave principal.
  • Elimina un registro, al menos anota el contenido de este registro, de modo que cuando retroceda más tarde, pueda insertar los registros compuestos por estos contenidos en la tabla
  • Si modifica un registro, debe registrar al menos el valor anterior antes de modificar este registro, de modo que pueda actualizar este registro al valor anterior cuando retroceda más tarde.

Estas cosas registradas por la base de datos para la reversión se denominan registros de deshacer, y el nombre en inglés undo logse llama undo日志. Una cosa a tener en cuenta aquí es que dado que la operación de consulta (SELECCIONAR) no modifica ningún registro de usuario, no es necesario registrar el registro correspondiente cuando se ejecuta la operación de consulta undo. En realidad InnoDB, undoel registro no es tan simple como lo dijimos anteriormente, y el formato del registro generado por diferentes tipos de operaciones undotambién es diferente, pero pongamos estos detalles que son fáciles de confundir por un tiempo. cuál es la identificación de la transacción

2. Identificación de la transacción

2.1 Cuándo asignar un id a una transacción

Como dijimos anteriormente cuando aprendimos sobre la introducción a las transacciones, una transacción puede ser una 只读事务o una 读写事务:

  • Podemos START TRANSACTION READ ONLYabrir uno a través de una declaración 只读事务En una transacción de solo lectura, no podemos agregar, eliminar o modificar tablas ordinarias (tablas a las que también pueden acceder otras transacciones), pero podemos agregar, eliminar y modificar tablas temporales.
  • Podemos START TRANSACTION READ WRITEiniciar una transacción a través de una declaración 读写事务, o usar una declaración para abrir una transacción por defecto.En la transacción de lectura y escritura, podemos realizar operaciones de adición, eliminación, modificación y consulta en la tabla BEGIN.START TRANSACTION读写事务

Si las operaciones , , y se realizan en una tabla durante la ejecución de una transacción , InnoDBel motor de almacenamiento le asignará una única 事务id, de la siguiente manera:

  • Para 只读事务la transacción, solo cuando realiza operaciones de agregar, eliminar y modificar en una tabla temporal creada por un usuario por primera vez, asignará una identificación de transacción a esta transacción; de lo contrario, no asignará una identificación de transacción

    小提示:
    Como dijimos anteriormente, EXPLAINal ejecutar y analizar un plan de consulta para una declaración de consulta determinada, a veces verá un indicador de uso temporal en la columna Extra, lo que indica que se usará una tabla temporal interna al ejecutar la declaración de consulta. CREATE TEMPORARY TABLEEsta supuesta tabla temporal interna no es la misma que la tabla temporal del usuario que creamos manualmente. Cuando se revierte la transacción, no es necesario revertir la tabla temporal interna utilizada en la ejecución de la declaración SELECT .

  • Por 读写事务ejemplo, se asignará una identificación de transacción a una transacción solo cuando realice operaciones de agregar, eliminar o modificar en una tabla (incluidas las tablas temporales creadas por los usuarios) por primera vez; de lo contrario, no asignará una identificación de transacción.

A veces, aunque hemos habilitado uno 读写事务, la transacción está llena de declaraciones de consulta y no se ejecutan declaraciones de adición, eliminación o modificación, lo que significa que a esta transacción no se le asignará una identificación de transacción.

Después de hablar durante mucho tiempo, ¿cuál es el uso de la identificación de transacción? Esto se mantendrá en secreto por ahora, y hablaré en detalle paso a paso más adelante. Ahora solo sepa que a una transacción se le asignará una identificación de transacción única solo cuando la transacción realice cambios en los registros de la tabla.

2.2 Cómo se genera la identificación de la transacción

Esto 事务ides esencialmente un número, y su estrategia de asignación es row_idaproximadamente la misma que la estrategia de asignación para columnas ocultas (columnas que InnoDB crea automáticamente cuando el usuario no crea una clave principal y una clave ÚNICA para la tabla) que mencionamos anteriormente. es como sigue:

  • El servidor mantendrá una variable global en la memoria. Siempre que sea necesario asignar una transacción 事务id, el valor de la variable se asignará a la transacción como la identificación de la transacción, y la variable se incrementará en 1
  • Siempre que el valor de esta variable 256sea un múltiplo de , el valor de esta variable se actualizará a un Max Trx IDatributo llamado en la página número 5 del espacio de tabla del sistema. El 占用8个字节espacio de almacenamiento de este atributo
  • Cuando el sistema se reinicie la próxima vez, cargará Max Trx IDlos atributos mencionados anteriormente en la memoria, agregará 256 al valor y lo asignará a la variable global que mencionamos anteriormente (porque el valor de la
    variable ser mayor que Max Trx IDel valor del atributo)

Esto asegura que el valor de identificación de la transacción asignado en todo el sistema sea un número creciente. La transacción a la que se le asigna una identificación primero obtiene una identificación de transacción más pequeña, y la transacción a la que se le asigna una identificación luego obtiene una identificación de transacción más grande.

2.3 columna oculta trx_id

Cuando aprendimos InnoDBel formato de fila de registro, enfatizamos que además de guardar los datos completos del usuario, los registros del índice agrupado agregarán automáticamente una columna oculta llamada , trx_idsi roll_pointerel usuario es un usuario 没有在表中定义主键以及UNIQUE键, una row_idcolumna oculta llamada Lista. Entonces, la estructura real de un registro en una página se ve así:

inserte la descripción de la imagen aquí

Las columnas que contiene trx_idson bastante fáciles de entender y se encuentran justo donde se encuentra una declaración que realiza cambios en el registro del índice agrupado 事务对应的事务id(los cambios aquí pueden ser INSERT, DELETEu UPDATEoperaciones). En cuanto a roll_pointerlas columnas ocultas, las analizaremos más adelante~

3. Formato del registro de deshacer

Para darse cuenta de la atomicidad de la transacción, el motor de almacenamiento necesita escribir primero el registro correspondiente InnoDBcuando realmente realiza , o un registro. Generalmente cada vez que se realiza un cambio en un registro corresponde a un log, pero en algunas operaciones de actualización de registros también puede corresponder a 2 logs, de los cuales hablaremos más adelante. Durante la ejecución de una transacción, pueden existir varios registros, es decir, se deben registrar muchos registros correspondientes, y estos registros se numerarán desde el principio, es decir, se denominan No. 0 undo log, No. 1 undo log según el orden de generación No. 1 undo log, ..., No. n undo log, etc., este número también se llama .undoundoundo新增删除更新undoundo0undo no

Estos registros de deshacer se registran en páginas de tipo FIL_PAGE_UNDO_LOG(el número hexadecimal correspondiente es 0x0002, los estudiantes que hayan olvidado cuál es el tipo de página, deben volver atrás y mirar los capítulos anteriores). Estas páginas se pueden asignar desde el espacio de tabla del sistema o desde un espacio de tabla dedicado a almacenar registros de deshacer, que es la denominada undo tablespaceasignación interna. Sin embargo, hablaremos sobre cómo asignar undopáginas para almacenar registros más adelante. Ahora echemos un vistazo a qué tipo de undoregistros se generarán mediante diferentes operaciones ~ Para el desarrollo fluido de la historia, primero creemos una demo18tabla llamada:

mysql> CREATE TABLE demo18 (
    id INT NOT NULL,
    key1 VARCHAR(100),
    col VARCHAR(100),
    PRIMARY KEY (id),
    KEY idx_key1 (key1)
    )Engine=InnoDB CHARSET=utf8;
Query OK, 0 rows affected, 1 warning (0.06 sec)

Hay 3 columnas en esta tabla, entre las cuales idla columna es la clave principal, hemos key1creado una para la columna 二级索引y la columna col es una columna ordinaria. Como mencionamos en el diccionario de datos que presentamos anteriormente InnoDB, a cada tabla se le asignará una única table id, podemos verificar a qué corresponde una determinada tabla a través de las tablas information_schemaen la base de datos del sistema , ahora veamos a cuánto corresponde :innodb_tablestable iddemo18table id

mysql> SELECT * FROM information_schema.innodb_tables WHERE name = 'testdb/demo18';
+----------+---------------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
| TABLE_ID | NAME          | FLAG | N_COLS | SPACE | ROW_FORMAT | ZIP_PAGE_SIZE | SPACE_TYPE | INSTANT_COLS | TOTAL_ROW_VERSIONS |
+----------+---------------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
|     1128 | testdb/demo18 |   33 |      6 |    66 | Dynamic    |             0 | Single     |            0 |                  0 |
+----------+---------------+------+--------+-------+------------+---------------+------------+--------------+--------------------+
1 row in set (0.00 sec)

Como se puede ver en los resultados de la consulta, demo18la tabla corresponde table ida 1128, primero recuerde este valor, lo usaremos más adelante

3.1 El registro de deshacer correspondiente a la operación INSERTAR

Como dijimos antes, cuando insertamos un registro en la tabla, habrá una distinción entre 乐观插入y 悲观插入, pero no importa cómo lo insertes, el resultado final es que este registro se coloca en una página de datos. Si desea revertir la operación de inserción, simplemente elimine este registro, es decir, al escribir el undoregistro correspondiente, registre principalmente la información de la clave principal de este registro. Por lo tanto, InnoDBse diseña un registro TRX_UNDO_INSERT_RECde tipo undo, y su estructura completa se muestra en la siguiente figura:

inserte la descripción de la imagen aquí
Según el diagrama, destacamos algunos puntos:

  • undo noSí en una transacción 从0开始递增, es decir, mientras la transacción no esté comprometida, cada vez que se genere un registro de deshacer, el no deshacer del registro aumentará en 1.

  • Si la clave principal en el registro contiene solo una columna, solo necesita registrar la suma ocupada por la columna en el tipo TRX_UNDO_INSERT_RECde registro, y si la clave principal en el registro contiene , entonces todos los ocupados deben registrarse (en el figura representa la columna ocupada El tamaño del espacio de almacenamiento representa el valor real de la columna).undo存储空间大小真实值多个列每个列存储空间大小和对应的真实值lenvalue

    小提示:
    Cuando insertamos un registro en una tabla, en realidad necesitamos insertar un registro en el índice agrupado y en todos los índices secundarios. Sin embargo, al grabar registros de deshacer, solo debemos considerar la situación al insertar registros en el índice agrupado porque, de hecho, los registros del índice agrupado y los registros del índice secundario tienen una correspondencia uno a uno. operación, solo necesitamos conocer la información de la clave principal de este registro
    , y luego realizar la operación de eliminación correspondiente de acuerdo con la información de la clave principal. Cuando se realiza la operación de eliminación, los registros correspondientes en todos los índices secundarios también se eliminarán. Los registros de deshacer correspondientes a la operación ELIMINAR y la operación ACTUALIZAR que se mencionan más adelante también son para los registros del índice agrupado y no lo enfatizaremos más adelante.

Ahora insertamos dos registros en demo18:

mysql> BEGIN;  # 显式开启一个事务,假设该事务的id为100
Query OK, 0 rows affected (0.00 sec)

mysql> # 插入两条记录
mysql> INSERT INTO demo18(id, key1, col) VALUES (1, 'AWM', '狙击枪'), (2, 'M416', '步枪');
Query OK, 2 rows affected (0.01 sec)
Records: 2  Duplicates: 0  Warnings: 0

Debido a que la clave primaria del registro contiene solo una columna, solo necesitamos registrar la longitud ( ) y el espacio de almacenamiento que ocupa la columna para insertarla en el registro iden el registro correspondiente . En este ejemplo, se insertan dos registros, por lo que se generarán dos registros de tipo :undoidid列的类型为INT,INT类型占用的存储空间长度为4个字节真实值TRX_UNDO_INSERT_RECundo

  • El primer undoregistro undo noes 0, la longitud del espacio de almacenamiento ocupado por la clave principal del registro es 4, y el valor real es 1. Dibuja un esquema como este:
    inserte la descripción de la imagen aquí
  • En el segundo undoregistro , la longitud del espacio de almacenamiento ocupado por la clave principal del registro es y el valor real es . Dibuja un esquema como este:undo no142
    inserte la descripción de la imagen aquí

En comparación con el primer artículo undo日志, undo nohay 主键各列信息una diferencia.

El significado de la columna oculta roll_pointer

Es hora de develar roll_pointerel verdadero velo. Este 7campo que ocupa 3 bytes en realidad no tiene ningún misterio. Es esencialmente un puntero al registro correspondiente undo日志的一个指针. demo18Por ejemplo, insertamos un registro en la tabla de arriba 2, y cada registro tiene su correspondiente undo日志. Los registros se almacenan en FIL_PAGE_INDEXpáginas de tipo (es decir, las páginas de datos de las que hemos estado hablando antes) y undolos registros se almacenan en FIL_PAGE_UNDO_LOGpáginas de tipo . El efecto se muestra en la figura:

inserte la descripción de la imagen aquí
También se puede ver de manera más intuitiva a partir de la figura que roll_pointerla esencia es un puntero al registro correspondiente al registro undo. roll_pointerSin embargo, el significado específico de cada byte de estos 7 bytes undose explicará en detalle después de que hablemos sobre cómo asignar páginas para almacenar registros ~

3.2 Undo log correspondiente a la operación DELETE

Sabemos que los registros insertados en la página formarán next_recorduna lista enlazada unidireccional de acuerdo con los atributos en la información del encabezado del registro. A esta lista enlazada la llamamos lista enlazada de registros normales, como dijimos antes cuando hablábamos de la estructura de la página de datos. , registros eliminados De hecho, también se formará una lista vinculada de acuerdo con los atributos en la información del encabezado del registro next_record, pero en esta lista vinculada 记录占用的存储空间可以被重新利用, por lo que esta lista vinculada también se llama 垃圾链表. PageHeaderLa sección tiene un PAGE_FREEatributo llamado , que apunta al nodo principal en la lista de elementos no utilizados que consta de registros eliminados. Para el buen desarrollo de la historia, primero dibujemos una imagen, suponiendo que la distribución de registros en una determinada página en este momento es así (este no es un demo18registro en la tabla, sino solo un ejemplo que citamos al azar):

inserte la descripción de la imagen aquí
Para resaltar el tema, en esta versión simplificada del diagrama esquemático, solo mostramos delete_masklas banderas de los registros. En la figura se puede ver que 正常记录链表中包含了3条正常记录, la lista enlazada basura contiene 2条已删除记录, y el espacio de almacenamiento ocupado por estos registros en la lista enlazada basura se puede reutilizar. Page HeaderEl valor de la propiedad de la parte de la página PAGE_FREErepresenta un puntero al nodo principal de la lista de elementos no utilizados. Suponiendo que vamos a utilizar DELETEla declaración 正常记录链表para eliminar el último registro en , de hecho, el proceso de eliminación debe pasar por dos etapas:

  • Fase 1: Solo delete_maskponer el bit de identificación del registro a 1, y no modificar los demás (de hecho, se modificarán los valores de estas columnas ocultas del registro trx_id) roll_pointer. InnoDB llama a esta etapa delete mark. Así es como se dibuja el proceso:

    inserte la descripción de la imagen aquíSe puede ver que el último registro en la lista enlazada de registros normales delete_mask值被设置为1no se agrega 垃圾链表. Es decir, el registro está en un estado en este momento 中间状态, y el registro eliminado ha estado en este supuesto estado hasta que se confirma la transacción en la que se confirma la declaración de eliminación 中间状态.

    小提示:
    ¿Por qué existe un estado intermedio tan extraño? De hecho, es principalmente para realizar una función llamada MVCC, jaja, la presentaré más adelante.

  • Fase 2: 当该删除语句所在的事务提交之后, habrá 专门的线程un borrado real del registro más adelante. La llamada eliminación real consiste en eliminar el 正常记录链表registro y 垃圾链表agregarlo, y luego ajustar alguna otra información de la página, como la cantidad de registros de usuario en la página PAGE_N_RECS, la posición del último registro insertado PAGE_LAST_INSERT, el puntero del nodo principal de la lista de elementos no utilizados PAGE_FREE, la cantidad de bytes que se pueden reutilizar en la página PAGE_GARBAGEy alguna información sobre el directorio de la página, etc. InnoDB llama a esta fase purge.

    Una vez 阶段二completada la ejecución, el registro se elimina realmente. El espacio de almacenamiento ocupado por este registro eliminado también se puede reutilizar. Así es como se dibuja: comparando con la imagen, también debemos prestar atención a un punto, al agregar el registro eliminado a la lista de basura, en realidad modificará el valor del atributo
    inserte la descripción de la imagen aquí
    cuando se agregue .链表的头节点处PAGE_FREE

    小提示:
    La parte del encabezado de página de la página tiene un atributo PAGE_GARBAGE, que registra el número total de bytes ocupados por el espacio de almacenamiento reutilizable en la página actual. Siempre que se agregue un registro eliminado a la lista de basura, el valor del atributo PAGE_GARBAGE se agregará al espacio de almacenamiento ocupado por el registro eliminado. PAGE_FREE apunta al nodo principal de la lista de elementos no utilizados, y luego cada vez que se inserta un nuevo registro, primero juzgue si el espacio de almacenamiento ocupado por el registro eliminado representado por el nodo principal al que apunta PAGE_FREE es suficiente para acomodar el registro recién insertado, si no, solicite directamente un nuevo espacio en la página para almacenar este registro (sí, leyó bien, no intentará atravesar toda la lista de basura para encontrar un nodo que pueda acomodar el nuevo registro). Si se puede acomodar, reutilice directamente el espacio de almacenamiento de este registro eliminado y señale PAGE_FREE al siguiente registro eliminado en la lista de elementos no utilizados. Pero aquí hay un problema: si el espacio de almacenamiento ocupado por el registro recién insertado es más pequeño que el espacio de almacenamiento ocupado por el nodo principal de la lista basura, significa que parte del espacio de almacenamiento ocupado por el registro correspondiente al nodo principal no se utiliza Esta parte del espacio se llama el espacio de escombros. ¿No se utilizarían para siempre estos espacios fragmentados? De hecho, no lo es. El tamaño del espacio de almacenamiento ocupado por estos espacios fragmentados se contará en el atributo PAGE_GARBAGE. Estos espacios fragmentados no se reutilizarán hasta que toda la página esté casi agotada. Sin embargo, cuando la página esté casi llena , si inserta otro registro, en este momento, el espacio para un registro completo no se puede asignar en la página. En este momento, primero verificaremos si el espacio combinado de PAGE_GARBAGE y el espacio disponible restante pueden acomodar este registro. Si es posible , InnoDB intentará reorganizar El proceso de reorganización de los registros en la página es abrir primero una página temporal, insertar los registros en la página uno por uno, porque no se generarán fragmentos al insertar en secuencia, y luego copiar el contenido de la página temporal a esta página, para que pueda liberar esos espacios fragmentados (obviamente, reorganizar los registros en la página consume más rendimiento).

De la descripción anterior, también podemos ver que antes de la transacción en la que se confirma la declaración de eliminación, solo pasará por la fase uno, es decir, la delete markfase (no necesitamos retroceder después de confirmar, por lo que solo debemos considerar realizando la fase uno de la operación de eliminación afectada por la reversión). InnoDBPara ello se diseña un TRX_UNDO_DEL_MARK_RECtipo de bitácora undo, cuya estructura completa se muestra en la siguiente figura:

inserte la descripción de la imagen aquíDios mío, hay demasiados atributos en esto ~ (De hecho, el significado de la mayoría de los atributos se ha presentado anteriormente) Sí, de hecho hay muchos, pero no preste atención, si no puede recordar a Don No te fuerces, los estoy enumerando todos aquí para que todos se familiaricen. Me gustaría molestar a todos para que primero superen el trastorno de pánico intensivo y luego busquen los atributos en el registro de este tipo anterior, prestando especial atención a estos puntos TRX_UNDO_DEL_MARK_REC:undo

  • Antes de operar en un registro delete mark, los valores de columna antiguos trx_idy roll_pointerocultos del registro deben registrarse en el registro correspondiente , que es el atributo de suma undoque se muestra en nuestra figura . Esto tiene la ventaja de que el registro correspondiente al registro antes de la modificación se puede encontrar a través del registro . Por ejemplo, en una transacción, primero insertamos un registro y luego realizamos una operación de eliminación en el registro. El diagrama esquemático de este proceso es el siguiente:oldtrx_idold roll_pointerundoold roll_pointerundo

    inserte la descripción de la imagen aquí

  • Puede verse en la figura que delete markdespués de ejecutar la operación, su undoregistro correspondiente y el registro INSERTcorrespondiente undode la operación forman una lista enlazada. Esto es muy interesante. Esta lista enlazada se llama 版本链. Ahora parece que no podemos ver el uso de esta cadena de versiones. Echemos un vistazo más adelante. Después de hablar sobre el registro UPDATEcorrespondiente undode la operación, esta supuesta cadena de versiones mostrarse lentamente fuera de su lugar contundente.

  • A diferencia del log de tipo TRX_UNDO_INSERT_REC, undoel log de tipo TRX_UNDO_DEL_MARK_RECtiene undoun 索引列各列信息contenido más, es decir, si una columna está incluida en un índice, su información relacionada debe registrarse en esta 索引列各列信息parte, la llamada información relacionada que incluye la posición de la columna en el registro (indicado pospor ), el espacio de almacenamiento ocupado por la columna (indicado lenpor ) y el valor real de la columna (indicado por value). Entonces, 索引列各列信息el contenido almacenado es esencialmente <pos, len, value>una lista de archivos . Esta parte de la información se usa principalmente en 中间状态记录la segunda etapa de la eliminación real después de que se confirma la transacción, es decir, se purgeusa en la etapa. Cómo usarla puede ignorarse ahora ~

Hemos terminado la introducción, ahora continuamos eliminando un registro en la transacción anterior idpara la transacción, por ejemplo, eliminamos el registro para :100id1

mysql> DELETE FROM demo18 WHERE id = 1;
Query OK, 1 row affected (0.01 sec)

delete markLa estructura del log correspondiente a esta operación undoes la siguiente:
inserte la descripción de la imagen aquísegún esta figura, debemos prestar atención a los siguientes puntos:

  • Porque este registro de deshacer se genera en la transacción con id 100 第3条undo日志,所以它对应的undo no就是2.

  • Al operar sobre el registro delete mark, trx_idel valor de la columna oculta del registro es 100(es decir, la última modificación del registro ocurrida en esta transacción), por lo tanto, complete 100el old trx_idatributo. Luego, saque roll_pointerel valor de la columna oculta del registro y rellénelo old roll_pointeren el atributo, de modo que el registro old roll_pointergenerado cuando se modificó el registro por última vez se pueda encontrar a través del valor del atributo .undo

  • Dado que hay 2 índices en la tabla demo18: 一个是聚簇索引, uno es 二级索引idx_key1. posSiempre que sea una columna incluida en el índice, la posición ( ), el espacio de almacenamiento ocupado ( len) y el valor real ( ) de esta columna en el registro valuedeben almacenarse en el registro de deshacer.

    • Para la clave principal, solo hay una idcolumna y la información relevante almacenada en el registro de deshacer es:

      • pos: idLa columna es la clave primaria, es decir, se registra 第一个列, y su valor pos correspondiente es 0. pos toma 1 byte para almacenar.

      • len: El tipo de la columna id es INT, ocupando 4 bytes, por lo que el valor de len es 4. len ocupa 1 byte para almacenar.

      • value: El valor de la columna id en el registro eliminado es 1, es decir, el valor del valor es 1. el valor tarda 4 bytes en almacenarse.

      • Haz un dibujo para demostrarlo así:
        inserte la descripción de la imagen aquí

      • Entonces, para idla columna, el resultado de almacenamiento final es < 0, 4, 1>, y el espacio de almacenamiento ocupado al almacenar esta información es 1 + 1 + 4 = 6个字节.

    • Para idx_key1, solo hay una key1columna, y undola información relevante almacenada en el registro es:

      • pos: La columna key1 se organiza después de la columna id, la columna trx_id y la columna roll_pointer, y su valor pos correspondiente 3. pos toma 1 byte para almacenar.

      • len: El tipo de la columna key1 es VARCHAR(100), y se utiliza el conjunto de caracteres utf8. El contenido de almacenamiento real del registro eliminado es AWM, por lo que ocupa un total de 3 bytes, es decir, el valor de len es 3 . len ocupa 1 byte para almacenar.

      • value: El valor de la columna clave1 en el registro eliminado es AWM, es decir, el valor del valor es AWM. el valor tarda 3 bytes en almacenarse.

      • Haz un dibujo para demostrarlo así:inserte la descripción de la imagen aquí

      • Entonces, para key1la columna, el resultado de almacenamiento final es < 3, 3, 'AWM'>, y el espacio de almacenamiento ocupado al almacenar esta información es 1 + 1 + 3 = 5bytes.

    Como puede verse en la descripción anterior, <0, 4, 1>y <3, 3, 'AWM'>ocupan 11un total de bytes. Luego index_col_info lenocupa 2un byte, por lo que ocupa un total de 13bytes, y el número 13 se completa index_col_info lenen el atributo.

3.3 Undo log correspondiente a la operación UPDATE

Al ejecutar UPDATEuna declaración, InnoDB maneja 更新主键estos 不更新主键dos casos de manera completamente diferente.

3.3.1 El caso en que la clave principal no se actualiza

En el caso de no actualizar la clave primaria, se puede subdividir en el caso en que el espacio de almacenamiento que ocupa la columna actualizada no cambia o cambia.

Actualización en el lugar (actualización en el lugar)

Al actualizar un registro, para cada columna que se actualizará, si el espacio de almacenamiento ocupado por la columna actualizada y la columna anterior a la actualización son iguales, entonces se puede realizar una actualización en el lugar, es decir, la columna correspondiente se puede actualizar directamente. modificado sobre la base del registro original El valor de la columna. Nuevamente, el espacio de almacenamiento ocupado por cada columna es el mismo antes y después de la actualización.Cualquier columna actualizada ocupa un espacio de almacenamiento mayor que el que ocupa después de la actualización, o el espacio de almacenamiento que ocupa antes de la actualización es menor que el que ocupa después de la actualización. lugar. Por ejemplo, hay un registro con un valor de id de 2 en la tabla demo18, y el tamaño de sus columnas se muestra en la figura (debido a que se usa el juego de caracteres utf8, los dos caracteres 'rifle' ocupan 6 bytes):

inserte la descripción de la imagen aquí
Supongamos que tenemos una declaración como esta UPDATE:

UPDATE demo18 SET key1 = 'P92', col = '手枪' WHERE id = 2;

En esta declaración UPDATE, la columna col se actualiza de un rifle a una pistola, ocupando 6 bytes antes y después, es decir, el espacio de almacenamiento ocupado no ha cambiado; la columna key1 se actualiza de M416 a P92, es decir, es cambió de 4
bytes La actualización es de 3 bytes, lo que no cumple con las condiciones requeridas para la actualización en el lugar, por lo que no se puede realizar la actualización en el lugar. Pero si la instrucción UPDATE se ve así:

UPDATE demo18 SET key1 = 'M249', col = '机枪'  WHERE id = 2;

Dado que el espacio de almacenamiento ocupado por cada columna actualizada es el mismo antes y después de la actualización, dicha declaración puede realizar una actualización en el lugar.

Elimine los registros antiguos primero, luego inserte los nuevos

En el caso de no actualizar la clave principal, si el espacio de almacenamiento ocupado por cualquiera de las columnas actualizadas es inconsistente antes y después de la actualización, primero debe eliminar este registro antiguo de la página de índice agrupado y luego de acuerdo con el valor de la columna actualizada crea un nuevo registro y lo inserta en la página.

Tenga en cuenta que la eliminación de la que estamos hablando aquí no es delete markuna operación, sino una eliminación real, es decir, eliminar este registro de la lista de registros normales y agregarlo a la lista de basura, y modificar la información estadística correspondiente en la página (Para ejemplo PAGE_FREE, PAGE_GARBAGEespere esta información). Sin embargo, el subproceso que realiza la operación de eliminación real aquí no es otro subproceso especial que se usa cuando se realiza la operación en la declaración persistente, sino que la operación de eliminación real se realiza de forma sincrónica por el subproceso del usuario.Después de la eliminación real, debe actualizarse de acuerdo con cada DELETEcolumnapurge

Aquí, si el espacio de almacenamiento ocupado por el registro recién creado no excede el espacio ocupado por el registro anterior, puede reutilizar directamente el espacio de almacenamiento ocupado por el registro anterior agregado a la lista de elementos no utilizados; de lo contrario, debe solicitar uno nuevo. sección de espacio en la página para Se usa el nuevo registro, si no hay espacio disponible en esta página, entonces se requiere la operación de división de página y luego se inserta un nuevo registro.

Para la situación en la que UPDATE no actualiza la clave principal (incluida la actualización en el lugar mencionada anteriormente y primero elimina el registro anterior y luego inserta el nuevo registro), InnoDB diseñó un tipo de registro de deshacer, su estructura completa es la siguiente TRX_UNDO_UPD_EXIST_REC:

inserte la descripción de la imagen aquí
TRX_UNDO_DEL_MARK_RECDe hecho, la mayoría de las propiedades son similares a los tipos de registros de deshacer que hemos introducido , pero aún debemos prestar atención a los siguientes puntos:

  • n_updatedEl atributo indica que varias columnas se actualizarán después de la ejecución de esta instrucción UPDATE, y las siguientes <pos, old_len, old_value>indican respectivamente la posición de la columna actualizada en el registro, el espacio de almacenamiento ocupado por la columna antes de la actualización y el valor real de la columna antes de la actualización.
  • Si UPDATEla columna actualizada en el extracto incluye una columna de índice, también se agregará la información de la columna de índice, de lo contrario, esta parte no se agregará.

Ahora continúe actualizando un registro en la transacción anterior idpara la transacción, por ejemplo, actualicemos el registro para :100id2

BEGIN;  # 显式开启一个事务,假设该事务的id为100
# 插入两条记录
INSERT INTO demo18(id, key1, col) VALUES (1, 'AWM', '狙击枪'), (2, 'M416', '步枪');
   
# 删除一条记录   
DELETE FROM demo18 WHERE id = 1;
# 更新一条记录
UPDATE demo18 SET key1 = 'M249', col = '机枪' WHERE id = 2;

UPDATEEl tamaño de la columna actualizada por esta declaración no ha cambiado, por lo que 采用就地更新se puede ejecutar de la siguiente manera: al cambiar el registro de la página, TRX_UNDO_UPD_EXIST_RECprimero se registrará un registro de deshacer, que se ve así:

inserte la descripción de la imagen aquí
Con esta imagen, prestemos atención a estos lugares como:

  • Debido a que este undoregistro es el primer registro generado en la transacción id, corresponde a .1004undoundo no3
  • El registro roll_pointerque apunta undo noa 1 de este registro es 2el registro generado cuando se inserta el registro con el valor de clave principal undo, es decir, el registro generado cuando se cambió el registro por última vez undo.
  • Dado que el valor de UPDATEla columna de índice se actualiza en esta declaración key1, es necesario registrar la información de cada columna de la columna de índice, es decir, completar key1la información de la clave principal y la columna antes de actualizar.

3.3.2 El caso de actualización de la clave primaria

En el índice agrupado, los registros están conectados en una lista unidireccional según el tamaño del valor de la clave principal. Si actualizamos el valor de la clave principal de un registro, significa que la posición de este registro en el índice agrupado cambiará. cambio Cambie, por ejemplo, si registrará 主键值从1更新为10000, si hay muchos registros cuyos valores de clave principal se distribuyen entre 1 y 10000, entonces estos dos registros pueden estar muy separados en el índice agrupado, o incluso separados en el medio Tantas páginas. En UPDATEel caso de que el valor de la clave principal del registro se actualice en la declaración, InnoDBel índice agrupado se procesa en dos pasos:

  • Operación de borrar marca en registros antiguos

    高能注意:¡Aquí está la operación de borrar marca! Es decir, UPDATEantes de que se confirme la transacción de la declaración, solo delete markse realiza una operación en el registro anterior, y después de que se confirme la transacción, un subproceso especial realiza purgela operación y la agrega a la lista de elementos no utilizados. Esto debe distinguirse de lo que dijimos anteriormente de que cuando el valor de la clave principal del registro no se actualiza, el registro anterior se elimina primero y luego se inserta el nuevo registro.

    小提示:
    La razón por la que la operación de eliminar marca solo se realiza en el registro anterior es que otras transacciones también pueden acceder a este registro al mismo tiempo. Si realmente se elimina y se agrega a la lista de basura, otras transacciones no podrán acceder a él. Esta función es la llamada MVCC, y hablaremos de lo que es un MVCC en detalle en los siguientes capítulos.

  • Cree un nuevo registro basado en los valores actualizados de cada columna e insértelo en el índice agrupado (es necesario cambiar la posición de la posición insertada).

    Dado que el valor de la clave principal del registro actualizado ha cambiado, es necesario reubicar la ubicación de este registro desde el índice agrupado y luego insertarlo.

Para UPDATEel caso en que la instrucción actualice el valor de la clave primaria del registro, antes de operar sobre el registro delete mark, se registrará un registro de tipo deshacer TRX_UNDO_DEL_MARK_REC; cuando posteriormente se inserte un nuevo registro, se registrará un registro de tipo TRX_UNDO_INSERT_REC, undoes decir, uno registro para cada par Cuando se cambia el valor de la clave principal, se registrarán dos registros de deshacer. Hemos hablado sobre el formato de estos registros anteriormente, por lo que no entraré en detalles.

4. Estructura general de la lista enlazada

En 写入undo日志el proceso se utilizarán múltiples listas vinculadas, y muchas listas vinculadas tienen la misma estructura de nodos, como se muestra en la figura:

inserte la descripción de la imagen aquí
En un determinado espacio de tabla, podemos ubicar de manera única la posición de un nodo a través del número de página de una página y el desplazamiento dentro de la página.Estas dos piezas de información son equivalentes a un puntero que apunta a este nodo. entonces:

  • Pre Node Page NumberLa combinación de y Pre Node Offsetes un puntero al nodo anterior.
  • Next Node Page NumberLa combinación de y Next Node Offsetes un puntero al siguiente nodo.

El conjunto List Nodeocupa 12 bytes de espacio de almacenamiento. Para administrar mejor la lista enlazada, InnoDB propone uno 基节点的结构, que almacena esto 链表的头节点, 尾节点y 链表长度信息el diagrama de estructura del nodo base es el siguiente:

inserte la descripción de la imagen aquí
en:

  • List LengthIndica cuántos nodos hay en la lista enlazada.
  • First Node Page Number和First Node OffsetLa combinación es un puntero al nodo principal de la lista enlazada.
  • Last Node Page Number和Last Node OffsetLa combinación es un puntero al nodo final de la lista enlazada.

El conjunto List Base Nodeocupa 16bytes de espacio de almacenamiento. Entonces, el diagrama esquemático del uso List Base Nodede la List Nodelista enlazada compuesta por estas dos estructuras es así:

inserte la descripción de la imagen aquí

Cinco, página FIL_PAGE_UNDO_LOG

Cuando hablábamos antes sobre el espacio de tablas, dijimos que el espacio de tablas en realidad está compuesto por muchas 页面构成páginas 默认大小为16KB. Hay diferentes tipos de estas páginas. Por ejemplo, FIL_PAGE_INDEXlas páginas de tipo se usan para almacenar índices agrupados e índices secundarios, FIL_PAGE_TYPE_FSP_HDRlas páginas de tipo se usan para almacenar información de encabezado de espacio de tabla y varios otros tipos de páginas, uno de los cuales se llama Este FIL_PAGE_UNDO_LOGtipo de página se usa especialmente 存储undo日志, y la estructura general de este tipo de página se muestra en la siguiente figura (tome el tamaño predeterminado de 16 KB como ejemplo):

inserte la descripción de la imagen aquí
Una página de tipo FIL_PAGE_UNDO_LOGse denomina simplemente Undopágina. File HeaderLos y en la imagen de arriba File Trailerson las estructuras comunes de varias páginas. Hemos aprendido muchas veces antes, así que no entraré en detalles aquí. Undo Page Headeres Undo页面único, echemos un vistazo a su estructura:

inserte la descripción de la imagen aquí
El significado de cada atributo es el siguiente:

  • TRX_UNDO_PAGE_TYPE: Qué tipo de registros de deshacer se almacenarán en esta página.
    Anteriormente introdujimos varios tipos de registros de deshacer, que se pueden dividir en dos categorías:

    • TRX_UNDO_INSERT(Denotado por el decimal 1): el TRX_UNDO_INSERT_RECregistro de deshacer de tipo pertenece a esta categoría y generalmente se INSERTgenera mediante una declaración, o este tipo de registro UPDATEtambién se generará cuando la clave principal se actualice en la declaración .undo

    • TRX_UNDO_UPDATE(Denotado por el decimal 2), a excepción de los registros de tipo TRX_UNDO_INSERT_REC, undotodos los demás tipos de registros pertenecen a esta categoría, como el , etc. undoque mencionamos anteriormente , y los registros generados por la declaración generalmente pertenecen a esta categoría.TRX_UNDO_DEL_MARK_RECTRX_UNDO_UPD_EXIST_RECDELETEUPDATEundo

    Los valores opcionales de este TRX_UNDO_PAGE_TYPEatributo son los dos anteriores, que se utilizan para marcar qué categoría de registros se utiliza para almacenar esta página undo. Los registros de diferentes categorías undono se pueden almacenar juntos. Por ejemplo , si una página tiene valor de atributo deUndoun registros y no se pueden colocar otros tipos de registros de deshacer en esta página.TRX_UNDO_PAGE_TYPETRX_UNDO_INSERTTRX_UNDO_INSERT_RECundo

    小提示:
    La razón por la que los registros de deshacer se dividen en dos categorías es que los registros de deshacer de tipo TRX_UNDO_INSERT_REC se pueden eliminar directamente después de que se confirme la transacción, mientras que otros tipos de registros de deshacer también deben servir al llamado MVCC y no se pueden eliminar directamente. El procesamiento debe ser tratado de manera diferente. Por supuesto, si está confundido después de leer este pasaje, no necesita volver a leerlo. Ahora solo necesita saber que los registros de deshacer se dividen en dos categorías. Explicaremos más detalles más adelante.

  • TRX_UNDO_PAGE_START: indica dónde undose almacena el registro en la página actual o el desplazamiento inicial del primer undoregistro en esta página.

  • TRX_UNDO_PAGE_FREE: En correspondencia con lo anterior , indica el desplazamiento al final del TRX_UNDO_PAGE_STARTúltimo registro almacenado en la página actual , o a partir de esta posición, puede continuar escribiendo nuevos registros de deshacer.undo

    Suponiendo que ahora se escriben 3 registros de deshacer en la página, el diagrama esquemático de TRX_UNDO_PAGE_STARTy TRX_UNDO_PAGE_FREEes así:
    inserte la descripción de la imagen aquí
    Por supuesto, cuando no se escribe ningún registro de deshacer al principio, el valor de TRX_UNDO_PAGE_STARTy TRX_UNDO_PAGE_FREEes el mismo.

  • TRX_UNDO_PAGE_NODE: Representa una estructura de Nodo de Lista (nodo ordinario de la lista enlazada, que acabamos de mencionar arriba), este atributo se usará inmediatamente debajo, así que no se impaciente.

Seis, Deshacer lista enlazada de página

6.1 Deshacer lista enlazada de página en una sola transacción

Debido a que una transacción puede contener múltiples declaraciones, y una declaración puede cambiar varios registros, y cada registro debe registrarse antes de cambiar, por lo que durante la 1条或2条的undo日志ejecución de una transacción 产生很多undo日志, estos registros pueden no caber en una página, debe colocarse en múltiples páginas, y estas páginas están TRX_UNDO_PAGE_NODEconectadas en una lista enlazada a través de los atributos que introdujimos anteriormente :

inserte la descripción de la imagen aquíPuede echar un vistazo a la imagen de arriba y, al mismo tiempo, llamar a la primera página Deshacer en la lista vinculada como Deshacer first undo page, porque además first undo pagede los registros Undo Page Header, también registrará otra información de gestión. El resto de las páginas Deshacer lo llaman normal undo page.

Durante la ejecución de una transacción, las declaraciones INSERT, DELETEy UPDATEpueden ejecutarse de forma mixta, lo que significa que se generarán diferentes tipos de registros de deshacer. Pero como dijimos antes, la misma Undopágina almacena solo TRX_UNDO_INSERTgrandes categorías de registros de deshacer, o solo almacena TRX_UNDO_UPDATEgrandes categorías de registros de deshacer. De todos modos, no se pueden mezclar, por lo que es posible que se necesiten dos listas enlazadas de páginas de deshacer durante la ejecución de un transacción. , una se llama insert undolista enlazada y la otra se llama update undolista enlazada. Dibuje un diagrama esquemático como este:

inserte la descripción de la imagen aquí
Además, los logs InnoDBque se generan cuando se modifican los registros de las tablas ordinarias y las tablas temporales undodeben registrarse por separado (se explica más adelante), de modo que haya como máximo 4 Undolistas enlazadas compuestas por páginas como nodos en una transacción:
inserte la descripción de la imagen aquí
por supuesto, no al principio de la transacción Estas 4 listas vinculadas se asignarán para esta transacción, pero se asignarán a pedido. La estrategia de asignación específica es la siguiente:

  • Cuando la transacción acaba de comenzar, tampoco se asigna una lista enlazada de página Deshacer.
  • Cuando se inserta un registro en una tabla ordinaria o se realiza una operación de actualización de la clave primaria de un registro durante la ejecución de la transacción, se insert undole asignará una lista enlazada de una tabla ordinaria.
  • Cuando los registros de la tabla ordinaria se eliminen o actualicen durante la ejecución de la transacción, se update undole asignará una lista enlazada de la tabla ordinaria.
  • Cuando se inserta un registro en la tabla temporal o se realiza la operación de actualización de la clave primaria del registro durante la ejecución de la transacción, se le asignará una lista enlazada de la tabla temporal insert undo.
  • Cuando los registros de la tabla temporal se eliminen o actualicen durante la ejecución de la transacción, se update undole asignará una lista enlazada de la tabla temporal.
    Para resumir es: 什么时候需要啥时候再分配,不需要就不分配.

6.2 Deshacer lista enlazada de página en transacciones múltiples

Para mejorar la eficiencia de escritura del registro de deshacer tanto como sea posible, 不同事务执行过程中产生的undo日志需要被写入到不同的Undo页面链表中. Por ejemplo, ahora hay dos transacciones con ID de transacción 1 y 2 respectivamente, las llamamos trx 1sum respectivamente trx 2, asumiendo que durante la ejecución de estas dos transacciones:

  • trx 1La operación se realiza en la mesa ordinaria y la operación DELETEse realiza en la mesa temporal . Se asignará una lista enlazada , que son: INSERTUPDATE
    InnoDBtrx 13
    • update undoLista enlazada para tabla normal
    • insert undoLista enlazada para tabla temporal
    • Una lista enlazada contra una tabla temporal update undo.
  • trx 2 realizó operaciones de INSERCIÓN, ACTUALIZACIÓN y ELIMINACIÓN en tablas ordinarias, pero no realizó cambios en las tablas temporales.
    InnoDBSe trx 2asignará una lista enlazada 2, que son:
    • Insertar lista enlazada de deshacer para tabla ordinaria
    • Actualice la lista enlazada de deshacer para la tabla común.

En resumen, en el proceso trx 1y trx 2la ejecución, se deben asignar InnoDBun total de listas enlazadas de 5 páginas para estas dos transacciones. Así es como se dibuja una imagen:Undo

inserte la descripción de la imagen aquí
Si hay más transacciones, significa que se pueden generar más listas vinculadas a la página Deshacer.

7. El proceso de escritura específico del registro de deshacer

7.1 El concepto de segmento (Segment)

Si ha leído detenidamente el capítulo sobre espacio de tablas, debería quedar impresionado por el concepto de este segmento.Pasamos mucho espacio hablando de este concepto. En pocas palabras, este segmento es un concepto lógico, esencialmente compuesto por varias páginas dispersas y varias áreas completas. Por ejemplo, un índice de árbol B+ se divide en dos segmentos, un segmento de nodo de hoja y un segmento de nodo de no hoja, de modo que los nodos de hoja se puedan almacenar juntos tanto como sea posible, y los nodos de no hoja se puedan almacenar juntos tanto como sea posible. posible. Cada segmento corresponde a una estructura de Entrada INODE.Esta estructura de Entrada INODE describe diversa información de este segmento, como el ID del segmento, varios nodos base de lista enlazada en el segmento, y los números de página de las páginas dispersas, etc. en esta estructura Puede revisar el significado de cada atributo en el capítulo sobre espacio de tablas). También dijimos antes que para ubicar una Entrada INODE, InnoDB diseñó una Segment Headerestructura:

inserte la descripción de la imagen aquí
El conjunto Segment Headerocupa 10 bytes de tamaño, y el significado de cada atributo es el siguiente:

  • ID de espacio de la entrada INODE: ID del espacio de tabla donde se encuentra la estructura de entrada INODE.

  • Número de página de la entrada de INODE: el número de página de la estructura de entrada de INODE.

  • Compensación de bytes de INODE Ent: la compensación de la estructura de entrada de INODE en esta página

Conociendo el ID del espacio de la tabla, el número de página y el desplazamiento dentro de la página, ¿puede ubicar de manera única la dirección de una entrada de INODE?

小提士:
Los diversos conceptos de segmentos en esta parte se explican en detalle en el capítulo sobre el espacio de la tabla. Lo mencionaré aquí solo para despertar su memoria dormida. Si tiene algún punto que no esté claro, puede volver al espacio de la tabla nuevamente. Lea cuidadosamente

7.2 Deshacer encabezado de segmento de registro

InnoDBSegún la normativa, cada lista enlazada de página Deshacer corresponde a un segmento, denominado Undo Log Segment. Es decir, todas las páginas de la lista enlazada se solicitan desde esta sección, por lo que diseñaron first undo pageuna Undo Log Segment Headerparte llamada primera página de la lista enlazada de página Deshacer, que es la mencionada anteriormente, esta parte contiene la información de la segmento correspondiente a la lista vinculada segment headery otra información sobre este segmento, por lo que Undo页la primera página de la lista vinculada en realidad se ve así:

inserte la descripción de la imagen aquí
Puedes ver que Undo链表la primera página de esta página es más que la página normal Undo Log Segment Header, echemos un vistazo a su estructura:

inserte la descripción de la imagen aquí
El significado de cada atributo es el siguiente:

  • TRX_UNDO_STATE: ¿En qué estado se encuentra la lista vinculada de la página Deshacer? Un Undo Log Segmentposible estado incluye lo siguiente:

    • TRX_UNDO_ACTIVE: Estado activo, es decir, una transacción activa está escribiendo registros de deshacer en este segmento.

    • TRX_UNDO_CACHED: El estado almacenado en caché. La lista enlazada de la página Deshacer en este estado está a la espera de ser reutilizada por otras transacciones.

    • TRX_UNDO_TO_FREE: Para la lista enlazada de deshacer de inserción, si la lista enlazada no se puede reutilizar después de que se confirme su transacción correspondiente, estará en este estado.

    • TRX_UNDO_TO_PURGE: Para la actualización de la lista enlazada de deshacer, si la lista enlazada no se puede reutilizar después de que se confirme su transacción correspondiente, estará en este estado.

    • TRX_UNDO_PREPARED: Contiene registros de deshacer generados por transacciones en la fase PREPARAR

    小提士:
    Cuándo y cómo se reutilizará la lista vinculada de la página Deshacer se discutirá en detalle más adelante. La etapa PREPARAR de la transacción solo aparece en la llamada transacción distribuida.Este libro no introducirá más sobre las transacciones distribuidas, por lo que puede ignorar este estado por ahora.

  • TRX_UNDO_LAST_LOG: La última posición en la lista enlazada de la página Deshacer Undo Log Header.

  • TRX_UNDO_FSEG_HEADERUndo: La información del segmento correspondiente a la lista enlazada de esta página Segment Header(es decir, la estructura de 10 bytes que introdujimos en el apartado anterior, a través de la cual puedes encontrar el segmento correspondiente INODE Entry)

  • TRX_UNDO_PAGE_LIST: El nodo base de la lista de páginas Deshacer.

    Dijimos anteriormente que la parte del encabezado de la página Deshacer de la página Deshacer tiene un TRX_UNDO_PAGE_NODEatributo de 12 bytes, que representa una List Nodeestructura. Cada Undopágina contiene Undo Page Headeruna estructura y estas páginas se pueden vincular en una lista vinculada a través de esta propiedad. Este TRX_UNDO_PAGE_LISTatributo representa el nodo base de esta lista enlazada, por supuesto, este nodo base solo existe en la Undoprimera página de la lista enlazada de páginas, es decir, first undo pageen.

Deshacer encabezado de registro

La forma en que una transacción Undoescribe undoun registro en una página es muy simple y violenta, es decir, escribe directamente en ella y escribe otro inmediatamente después de escribir uno, y cada undoregistro es íntimo. Después de escribir una página Deshacer, solicite una nueva página del segmento, luego inserte esta página en la lista vinculada de la página Deshacer y continúe escribiendo en la página recién aplicada. InnoDB considera los registros de deshacer escritos en una lista vinculada de página Deshacer por la misma transacción como un grupo. Por ejemplo, el trx 1 que presentamos anteriormente asignará 3 listas vinculadas de página Deshacer, por lo que también escribirá 3 grupos de registros de deshacer; Dado que trx 2 asignará 2 listas enlazadas de páginas de deshacer, también escribirá 2 grupos de registros de deshacer. Cada vez que se escribe un grupo de registros de deshacer, algunos atributos sobre este grupo se registrarán antes de este grupo de registros de deshacer.InnoDB llama al lugar donde se almacenan estos atributos Undo Log Header. Por lo tanto, antes de que la primera página de la lista de páginas Deshacer se escriba en el registro de deshacer, en realidad se llenará con U ndo Page Header, estas tres partes, como se muestra en la figura:Undo Log Segment HeaderUndo Log Header

inserte la descripción de la imagen aquí
La Undo Log Headerestructura específica es la siguiente:

inserte la descripción de la imagen aquí
Hay muchos atributos nuevamente, echemos un vistazo a lo que significan:

  • TRX_UNDO_TRX_ID: Genere la identificación de transacción de este grupo de registros de deshacer

  • TRX_UNDO_TRX_NO: Se genera un número de secuencia después de que se confirma la transacción, y este número de secuencia se utiliza para marcar el orden de confirmación de la transacción (el número de secuencia enviado primero es pequeño y el número de secuencia enviado después es grande).

  • TRX_UNDO_DEL_MARKS: Marque si este grupo undode registros contiene Delete markregistros de deshacer generados debido a operaciones.

  • TRX_UNDO_LOG_START: Indica el desplazamiento de página del primer registro de deshacer en este grupo de registros de deshacer.

  • TRX_UNDO_XID_EXISTS: si este grupo de registros de deshacer contiene información XID.

  • TRX_UNDO_DICT_TRANS: marque si este grupo de registros de deshacer es generado por sentencias DDL.

  • TRX_UNDO_TABLE_ID: si TRX_UNDO_DICT_TRANS es verdadero, este atributo indica la identificación de la tabla operada por la instrucción DDL.

  • TRX_UNDO_NEXT_LOG: El desplazamiento en la página donde comienza el siguiente conjunto de registros de deshacer.

  • TRX_UNDO_PREV_LOG: El desplazamiento en la página donde comienzan los registros de deshacer del grupo anterior.

    小提士:
    En términos generales, una lista enlazada de página de deshacer solo almacena un conjunto de registros de deshacer generados durante la ejecución de una transacción, pero en algunos casos, después de confirmar una transacción, la siguiente transacción abierta puede reutilizar esta lista enlazada de página de deshacer, de modo que como Como resultado, se pueden almacenar varios conjuntos de registros de deshacer en una página de deshacer. TRX_UNDO_NEXT_LOG y TRX_UNDO_PREV_LOG se utilizan para marcar las compensaciones del siguiente conjunto y el conjunto anterior de registros de deshacer en la página. Con respecto a cuándo reutilizar la lista vinculada de la página Deshacer y cómo reutilizar esta lista vinculada, lo explicaremos en detalle más adelante. Por ahora, solo comprenda el significado de los dos atributos TRX_UNDO_NEXT_LOG y TRX_UNDO_PREV_LOG.

  • TRX_UNDO_HISTORY_NODE: una estructura de nodo de lista de 12 bytes que representa un nodo denominado lista vinculada de historial.

resumen

Para la lista de páginas vinculadas que no se ha reutilizado , se completará Undola primera página de la lista vinculada, es decir, antes de first undo pageque se escriba en el registro, y luego se escribirá oficialmente en el registro de deshacer. Para otras páginas, es decir, antes de escribir en el registro, solo se llenará . El almacenamiento de la lista enlazada , la información se almacena en la parte de cada página , así que dibuje un diagrama esquemático de la lista enlazada de la página como este:undoUndo Page Header、Undo Log Segment Header、Undo Log Header这3个部分normal undo pageundoUndo Page HeaderList Base Nodefirst undo page的Undo Log Segment Header部分List NodeUndoundo Page HeaderUndo

inserte la descripción de la imagen aquí

8. Reutilice la página Deshacer

Dijimos anteriormente que para mejorar el rendimiento de múltiples transacciones simultáneas escritas en undoel registro, InnoDBdecidimos asignar una Undolista vinculada de página correspondiente para cada transacción (se pueden asignar hasta 4 listas vinculadas por separado). Pero esto también causó algunos problemas. Por ejemplo, de hecho, solo uno o unos pocos registros pueden modificarse durante la ejecución de la mayoría de las transacciones. Para una determinada lista vinculada a la página Deshacer, solo se generan muy pocos registros de deshacer, y estos registros de deshacer pueden solo ocupan un poco Para el espacio de almacenamiento, Undo¿no sería demasiado derrochador crear ? De hecho, es bastante derrochador, por lo que InnoDB decidió reutilizar la lista de páginas de la transacción en algunos casos después de que se confirme la transacción Undo. Las condiciones para si una Undolista enlazada de páginas se puede reutilizar son simples:

  • La lista vinculada contiene solo una Undopágina.
    Si se genera una transacción durante la ejecución 非常多的undo日志, es posible que se agreguen muchas páginas a la lista vinculada de la página Deshacer. Después de enviar la transacción, si se reutilizan las páginas de toda la lista vinculada, significa que incluso si la nueva transacción no Undoescribe muchos undoregistros en la lista vinculada de páginas, se deben mantener muchas páginas en la lista vinculada. no están disponibles no pueden ser utilizados por otras empresas, lo que crea otro tipo de desperdicio. Por lo tanto InnoDB, solo Undocuando la lista de páginas Deshacer contiene solo una página, la siguiente transacción puede reutilizar la lista.

  • El espacio ya utilizado por la página Deshacer 小于整个页面空间的3/4
    Como dijimos anteriormente, la lista enlazada de la página Deshacer se puede dividir en insert undolista enlazada y update undolista enlazada de acuerdo con las categorías de los registros de deshacer almacenados.Estas dos listas enlazadas tienen diferentes estrategias cuando se reutilizan. respectivamente echar un vistazo

    • insertar lista de deshacer

      insert undoTRX_UNDO_INSERT_RECSolo los registros de tipo se almacenan en la lista enlazada undoEste tipo de registro de deshacer es inútil después de que la transacción se confirma y se puede borrar. Entonces, después de confirmar una transacción, al reutilizar la lista enlazada de inserción y deshacer de esta transacción (solo hay una página en esta lista enlazada), puede sobrescribir directamente un conjunto de registros de deshacer escritos por la transacción anterior y escribir un conjunto de deshacer registros para la nueva transacción desde cero, como se muestra en la siguiente figura:

      inserte la descripción de la imagen aquí
      Como se muestra en la figura, supongamos que hay una lista vinculada utilizada por una transacción insert undo. Cuando se confirma la transacción, solo se insertan 3 registros de deshacer en la lista vinculada de inserción de deshacer. Esta lista vinculada de inserción de deshacer solo se aplica a una página Deshacer. Suponiendo que en este momento 该页面已使用的空间小于整个页面大小的3/4, la próxima transacción pueda reutilizar esta insert undolista vinculada (solo hay una página en la lista vinculada). Suponiendo que una nueva transacción reutilice la insert undolista vinculada en este momento, el antiguo conjunto de registros de deshacer se puede sobrescribir directamente y se undopuede escribir un nuevo conjunto de registros.

    • actualizar deshacer lista vinculada
      Después de confirmar una transacción, los registros update undoen su lista vinculada undono se pueden eliminar inmediatamente (estos registros se usan para MVCC, de lo que hablaremos más adelante). Por lo tanto, si las transacciones posteriores desean reutilizar update undola lista vinculada, no pueden sobrescribir los registros escritos por transacciones anteriores undo. UndoEsto es equivalente a escribir varios grupos de registros en la misma página undo, y el efecto se ve así
      inserte la descripción de la imagen aquí

Nueve, segmento de reversión

9.1 El concepto de segmento rollback

Ahora sabemos que una transacción puede asignar hasta 4 listas vinculadas de páginas durante la ejecución Undo, y diferentes transacciones tienen diferentes Undolistas vinculadas de páginas al mismo tiempo, por lo que en realidad puede haber muchas listas vinculadas de páginas de deshacer en el sistema al mismo tiempo. Para administrar mejor estas listas enlazadas , InnoDBuna página llamada . Podemos entender que cada lista enlazada de página es equivalente a una clase, y esta lista enlazada es equivalente al monitor de esta clase. Si encuentra el monitor de esta clase, puede encontrar otros estudiantes en la clase (otros estudiantes son equivalentes ) . A veces la escuela necesita transmitir el espíritu a estas clases, y necesita llamar a todos los monitores a la sala de conferencias, que es el equivalente a una sala de conferencias.Rollback Segment HeaderUndofrist undo pageundo slotUndofirst undo pagenormal undo pageRollback Segment Header

Echemos un vistazo a Rollback Segment Headercómo se ve esta supuesta página (tome los 16 KB predeterminados como ejemplo):

inserte la descripción de la imagen aquí
InnoDBEstá estipulado que cada Rollback Segment Headerpágina corresponde a un segmento, y este segmento se llama Rollback Segment, es decir 回滚段. A diferencia de las diversas secciones que presentamos anteriormente, Rollback Segmenten realidad solo hay una página en esta (esto puede deberse InnoDBa que piensan que si quieren asignar páginas para un propósito determinado, primero deben solicitar una sección, o piensan que aunque la versión actual MySQLen realidad Rollback Segmentsolo tiene una página, pero es posible agregar páginas en versiones posteriores).

Después de entender Rollback Segmentel significado de , echemos un vistazo al Rollback Segment Headersignificado de cada parte de esta supuesta página:

  • TRX_RSEG_MAX_SIZE: El valor máximo de la suma del número de páginas en Rollback Segmenttodas las listas enlazadas de páginas administradas en este libro . En otras palabras, Ben .UndoUndoRollback Segment中所有Undo页面链表中的Undo页面数量之和不能超过TRX_RSEG_MAX_SIZE代表的值

    El valor de esta propiedad es infinito por defecto, es decir, podemos escribir tantas páginas Undo como queramos.

    小提士:
    Infinity es en realidad solo una exageración. El número más grande que se puede representar con 4 bytes es 0xFFFFFFFF, pero veremos más adelante que el número 0xFFFFFFFF tiene un propósito especial, por lo que el valor real de TRX_RSEG_MAX_SIZE es 0xFFFFFFFE.

  • TRX_RSEG_HISTORY_SIZE: HistoryEl número de páginas ocupadas por la lista enlazada.

  • TRX_RSEG_HISTORY: HistoryEl nodo base de la lista enlazada.

  • TRX_RSEG_FSEG_HEADER: Esta es una Rollback Segmentestructura de 10 bytes correspondiente a esta Segment Headersección, a través de la cual puede encontrar la sección correspondiente INODE Entry.

TRX_RSEG_UNDO_SLOTS: La colección de números de página de cada Undolista enlazada de páginas , es decir, la colección.first undo pageundo slot

Un número de página ocupa 4bytes. Para 16KBuna página de este tamaño, esta TRX_RSEG_UNDO_SLOTSparte almacena un total de 1024bytes undo slot, por lo que un total de 1024 × 4 = 4096个字节

9.2 Solicitar la lista enlazada de la página Deshacer desde el segmento de reversión

Inicialmente, dado que no Undose asigna ninguna lista vinculada a páginas a ninguna transacción, Rollback Segment Headercada una de ellas undo slotse establece en un valor especial para una página: FIL_NULL(el valor hexadecimal correspondiente es 0xFFFFFFFF), lo que indica que undo slotno apunta a ninguna página.

A medida que pasa el tiempo, hay transacciones que necesitan asignar Undolistas vinculadas a la página, así que comience desde la primera del segmento de reversión undo slotpara ver si undo slotel valor es FIL_NULL:

  • Si es así FIL_NULL, cree un nuevo segmento (es decir), en el espacio de tabla Undo Log Segmenty luego solicite una página del segmento como una Undolista de enlaces de página first undo page, y luego establezca undo slotel valor de esto en el número de página de la página que acaba de aplicar. , lo que significa Esto undo slotse asigna a esta transacción.

  • Si no FIL_NULL, significa que esta undo slotya apuntó a una undolista enlazada, es decir, esta undo slotha sido ocupada por otras transacciones, entonces salte a la siguiente undo slot, juzgue undo slotsi el valor de esta es correcto FIL_NULL, y repita los pasos anteriores.

Rollback Segment HeaderIncluido en una página 1024个undo slot, 1024si undo slotel valor de esta es none FIL_NULL, significa que 1024esta undo slotya ha sido nombrada (asignada a una determinada transacción). En este momento, debido a que la nueva transacción ya no puede obtener una nueva Undolista de páginas, se activará. devuelve la transacción e informa un error al usuario:

Too many active concurrent transactions

Cuando el usuario ve este error, puede optar por volver a ejecutar la transacción (tal vez se confirmen otras transacciones durante la reejecución y se le puede asignar una Undolista de páginas a la transacción).

Cuando se compromete una transacción, lo que ocupa undo slottiene dos destinos:

  • Si la lista enlazada de undo slotpáginas Undoa la que apunta cumple la condición de ser reutilizada (es decir, la lista enlazada de páginas Deshacer que mencionamos anteriormente solo ocupa una página y el espacio utilizado es menos de 3/4 de la página completa).

    Está undo sloten el estado de almacenamiento en caché, y InnoDBse estipula que el atributo Undode la lista de páginas enlazadas TRX_UNDO_STATE(la parte r first undo pagedel atributo Undo Log Segment Heade) se establecerá en TRX_UNDO_CACHED.

    Los almacenados en caché se agregarán a una lista vinculada y se agregarán a diferentes listas vinculadas undo slotsegún el tipo de lista vinculada de la página correspondiente :Undo

    • Si la Undolista vinculada de la página correspondiente es insert undouna lista vinculada, se undo slotagregará a insert undo cachedla lista vinculada.

    • Si la Undolista vinculada de la página correspondiente es update undouna lista vinculada, se undo slotagregará a update undo cachedla lista vinculada.

    Un segmento de reversión corresponde a las dos cachedlistas vinculadas anteriores. Si hay una nueva transacción para asignar , primero se encuentra en la lista vinculada undo slotcorrespondiente . cachedSi no está en caché undo slot, irá a la 的Rollback Segment Headerpágina del segmento de reversión para encontrarlo nuevamente.

  • Si la lista de enlaces de páginas undo slotseñalada Undono cumple la condición de ser reutilizada, entonces la lista de enlaces de páginas undo slotcorrespondiente Undose manejará de manera diferente según el tipo:

  • Si la Undolista vinculada de la página correspondiente es insert undouna lista vinculada, el atributo Undode la lista vinculada de la página TRX_UNDO_STATEse establecerá en , y luego se liberará TRX_UNDO_TO_FREEel segmento correspondiente a la lista vinculada de la página (lo que significa que las páginas del segmento se pueden utilizar para otros fines). Undo), y luego el undo slotvalor se establece en FIL_NULL.

  • Si la Undolista vinculada de la página correspondiente es update undouna lista vinculada, la propiedad Undode la lista vinculada de la página TRX_UNDO_STATEse establecerá en TRX_UNDO_TO_PRUGE, y undo slotel valor se establecerá en , y luego se colocará FIL_NULLun conjunto de registros escritos por esta transacción en la denominada lista vinculada. lista (tenga en cuenta que el segmento correspondiente a la lista enlazada de la página Deshacer no se publicará aquí, porque estos registros siguen siendo útiles ~)undoHistoryundo

9.3 Múltiples segmentos de reversión

Decimos que la mayoría se asigna durante la ejecución de una transacción 4个Undo页面链表, pero solo en un segmento de retroceso 1024个undo slot, obviamente undo slotel número es un poco pequeño. Incluso si asumimos que solo se asigna una lista vinculada a 1una página durante la ejecución de una transacción de lectura y escritura, eso solo puede admitir la ejecución simultánea de dos transacciones de lectura y escritura, y fallará si hay más. Esto es equivalente al hecho de que la sala de conferencias solo puede acomodar un monitor para realizar una reunión al mismo tiempo. Si miles de personas vienen a la sala de conferencias para una reunión al mismo tiempo, los monitores posteriores no tendrán lugar para sentarse. , y solo puede esperar a que las personas de enfrente terminen la reunión antes de entrar.Undo1024undo slot10241024

Se dice que, InnoDBde hecho, solo hay un segmento de reversión en la etapa inicial de desarrollo, pero InnoDBluego se dio cuenta de este problema, ¿cómo resolverlo? No hay suficientes salas de conferencias, por lo que necesitamos construir algunas salas de conferencias más. Por lo tanto InnoDB, definir 128un segmento de reversión de una vez es equivalente a tener uno 128 × 1024 = 131072个undo slot. Suponiendo que solo se asigna una lista vinculada a 1una página durante la ejecución de una transacción de lectura y escritura Undo, entonces 131072se puede admitir la ejecución simultánea de múltiples transacciones de lectura y escritura al mismo tiempo (nunca había visto tantas transacciones ejecutadas simultáneamente en una máquina ~)

Cada segmento de retroceso corresponde a una Rollback Segment Headerpágina. Si hay 128un segmento de retroceso, debe haber 128una Rollback Segment Headerpágina. ¡Las direcciones de estas páginas deben almacenarse en algún lugar! Por lo tanto, un área determinada de InnoDBla página No. del espacio de tablas del sistema 5contiene 128 cuadrículas de 8 bytes:

inserte la descripción de la imagen aquí
Cada cuadrícula de 8 bytes se construye así:

inserte la descripción de la imagen aquí
Como se muestra, cada cuadrícula de 8 bytes en realidad consta de dos partes:

  • 4 bytes de tamaño Space ID, que representa el ID de un tablespace.

  • 4 bytes de tamaño Page number, que representa un número de página.

Es decir, cada tamaño de 8 bytes 格子es equivalente a un puntero, que apunta a una determinada página en un determinado espacio de tablas, y estas páginas son Rollback Segment Header. Una cosa a tener en cuenta aquí es que para ubicar un encabezado de segmento de reversión, debe conocer el ID del espacio de tabla correspondiente, lo que significa que diferentes segmentos de reversión pueden distribuirse en diferentes espacios de tabla.

Entonces, a través de la descripción anterior, podemos entender aproximadamente que hay dos direcciones de página 5almacenadas en la página No. del espacio de tabla del sistema, cada una de las cuales es equivalente a un segmento de reversión. En la página, también contiene , cada uno correspondiente a una lista de páginas enlazadas. Dibujemos un diagrama:128Rollback Segment HeaderRollback Segment HeaderRollback Segment Header1024个undo slotundo slotUndo

inserte la descripción de la imagen aquí
Es mucho más refrescante una vez que se dibuja la imagen.

9.4 Clasificación de los segmentos de retroceso

Vamos a numerar los segmentos de retroceso 128. El segmento de retroceso inicial se llama segmento de retroceso No. 0, y luego se incrementa sucesivamente. El último segmento de retroceso se llama segmento de retroceso No. 127. Los 128 segmentos de retroceso se pueden dividir en dos categorías:

  • 第0号、第33~127号回滚段属于一类. Entre ellos, el segmento de reversión n.° 0 debe estar en el espacio de tabla del sistema (es decir, la página de encabezado de segmento de reversión correspondiente al segmento de reversión n.° 0 debe estar en el espacio de tabla del sistema), y los segmentos de reversión n.° 33 a 127 se pueden en el espacio de tabla del sistema En, o en el espacio de tabla de deshacer configurado por usted mismo, hablaremos sobre cómo configurarlo más adelante.

    Si una transacción necesita asignar una lista enlazada de página de deshacer debido a cambios en los registros de la tabla ordinaria durante la ejecución, se debe asignar el espacio de deshacer correspondiente desde este tipo de segmento.

  • 第1~32号回滚段属于一类. Estos segmentos de reversión deben estar en el tablespace temporal (correspondiente al archivo ibtmp1 en el directorio de datos).

    Si una transacción necesita asignar una lista enlazada de página Deshacer debido a cambios en los registros de la tabla temporal durante la ejecución, debe asignarse desde este tipo de segmento undo slot.

Es decir, si una transacción cambia tanto los registros de la tabla ordinaria como los registros de la tabla temporal durante la ejecución, es necesario asignar 2 segmentos de rollback para este registro, y luego pasar a los dos segmentos de rollback correspondientes a la asignación en el segmento undo slot.

No sé si tienes alguna duda, ¿por qué deberíamos dividir diferentes tipos de segmentos de rollback para tablas ordinarias y tablas temporales? Esto tiene que Undoempezar con la página en sí, decimos que Undouna página es en realidad FIL_PAGE_UNDO_LOGla abreviatura de una página de tipo , después de todo, también es una página ordinaria. Como dijimos antes, debe redoescribir el registro correspondiente antes de modificar la página, para que cuando el sistema se bloquee y reinicie, pueda restaurarse al estado antes del bloqueo. UndoEscribir logs en la página undoen sí es también un proceso de escritura de páginas, por eso InnoDBse diseñan muchos redotipos de logs , como MLOG_UNDO_HDR_CREATE, MLOG_UNDO_INSERT, , MLOG_UNDO_INITetc., es decir, cualquier cambio que hagamos Undoen la página registrará el correspondiente tipo de redoregistro. Pero para las tablas temporales, undolos registros generados al modificar las tablas temporales solo necesitan ser válidos durante la operación del sistema. Si el sistema falla, no es necesario restaurar las undopáginas donde se encuentran estos registros al reiniciar, por lo que al escribir para las tablas temporales Undohay no es necesario grabar el registro correspondiente para la página redo. Resuma las razones para dividir diferentes tipos de segmentos de reversión para tablas ordinarias y tablas temporales: al modificar las Undopáginas en los segmentos de reversión para tablas ordinarias, debe registrar los registros correspondientes y modificar las páginas redoen los segmentos de reversión para tablas temporales registro correspondiente.Undoredo

小提士:
Si solo realizamos cambios en los registros de la tabla ordinaria, solo se asignará a la transacción el segmento de reversión de la tabla ordinaria y no se asignará el segmento de reversión de la tabla temporal. Pero si solo hacemos cambios en los registros de la tabla temporal, entonces a la transacción se le asignará tanto el segmento de reversión para la tabla ordinaria como el segmento de reversión para la tabla temporal (pero la asignación del segmento de reversión no asignará inmediatamente el segmento de deshacer ranura, y solo asigne la ranura de deshacer en el segmento de reversión cuando la lista vinculada de la página Deshacer sea realmente necesaria).

9.5 Proceso detallado de asignación de la lista enlazada de la página Deshacer para la transacción

Undo页面Hay muchos conceptos mencionados anteriormente, y todos deberían sentirse un poco mareados. A continuación, tomemos el ejemplo de una transacción que cambia los registros de una tabla común para resolver el proceso completo de asignación de una lista vinculada durante la ejecución de la transacción.

  • Antes de realizar cualquier cambio en los registros de las tablas ordinarias por primera vez durante la ejecución de una transacción, primero asignará un segmento de reversión a la página 5 del espacio de tabla del sistema (de hecho, es para obtener la dirección de una página) Rollback Segment Header. Una vez que se asigna un determinado segmento de reversión a esta transacción, cuando los registros de la tabla ordinaria se cambien en la transacción más adelante, no se asignará repetidamente.

    Utilice el método legendario round-robin(reciclado) para asignar segmentos de reversión. Por ejemplo, si la transacción actual asigna el segmento de reversión n.° 0, la siguiente transacción asignará el segmento de reversión n.° 33 y la siguiente transacción asignará el segmento de reversión n.° 34. En pocas palabras, estos segmentos de reversión se asignan Asignación a diferentes asuntos a su vez (es tan simple y grosero, no hay nada que decir).

  • Después de asignar el segmento de reversión, primero verifique cachedsi las dos listas vinculadas del segmento de reversión se han almacenado en caché undo slot. Por ejemplo, si la transacción es INSERTuna operación, vaya a la lista vinculada i correspondiente al segmento de reversión nsert undo cachedpara ver si hay algún caché undo slot; Si la transacción es DELETEuna operación, vaya a la lista enlazada correspondiente al segmento de reversión update undo cachedpara ver si hay algún caché undo slot. Si hay un caché undo slot, entonces undo slotasigne este caché a la transacción.

  • Si no hay caché undo slotdisponible para la asignación, entonces es necesario Rollback Segment Headerencontrar una undo slotasignación disponible en la página para la transacción actual.

    Rollback Segment HeaderLa forma de asignar las páginas disponibles de la página undo slottambién se menciona anteriormente, es decir, a partir de la 0 undo slot, si el undo slotvalor de este valor FIL_NULLsignifica que undo slotestá libre, entonces undo slotasígnelo a la transacción actual, de lo contrario, verifique si la primera undo slotes condición satisfecha, y así sucesivamente, hasta la última undo slot. Si ninguna de las 1024 ranuras para deshacer tiene un valor FIL_NULL, solo informe un error (generalmente esto no sucederá) ~

  • Después de encontrar el disponible undo slot, si se undo slotobtiene de cachedla lista enlazada, entonces Undo Log Segmentse ha asignado el correspondiente; de ​​lo contrario, debe reasignarse Undo Log Segment, y luego Undo Log Segmentsolicitar una página como Undola lista enlazada de páginas first undo page.

  • ¡ Entonces la transacción puede undoescribir el registro en la aplicación anterior Undo页面链表了!

Los pasos para modificar los registros de la tabla temporal son los mismos que los descritos anteriormente, por lo que no los repetiré aquí. Sin embargo, debe enfatizarse nuevamente que si una transacción cambia tanto los registros de la tabla ordinaria como los registros de la tabla temporal durante la ejecución, entonces es necesario asignar 2 segmentos de reversión para este registro. De hecho, a diferentes transacciones ejecutadas simultáneamente también se les puede asignar el mismo segmento de reversión, siempre que se les asignen diferentes undo slot.

9.6 Configuración relacionada con el segmento de reversión

9.6.1 Configurar el número de segmentos de reversión

Dijimos anteriormente que hay un total de segmentos de reversión en el sistema 128. De hecho, este es solo el valor predeterminado. Podemos configurar la cantidad de segmentos de reversión a través de los parámetros de inicio innodb_rollback_segments. El rango configurable es 1~128. Pero este parámetro no afectará la cantidad de segmentos de reversión para tablas temporales, la cantidad de segmentos de reversión para tablas temporales siempre es 32, es decir:

  • Si innodb_rollback_segmentsestablecemos el valor en 1, solo habrá 1un segmento de reversión disponible para las tablas normales, pero aún habrá 32uno disponible para las tablas temporales.

  • Si innodb_rollback_segmentsestablecemos el valor en un número entre , el efecto es el mismo 2~33que establecerlo en .1

  • Si establecemos el número innodb_rollback_segmentsen 大于33, entonces el número de segmentos de reversión disponibles para las tablas ordinarias es 该值减去32.

9.6.2 Configurar el tablespace de deshacer

De forma predeterminada, los segmentos de reversión (segmentos numéricos 0y 33~127de reversión) configurados para tablas ordinarias se asignan al espacio de tablas del sistema. El 0segmento de reversión n.º 1 siempre está en el espacio de tabla del sistema, pero el segmento de reversión n.º 1 33~127se puede colocar en un undoespacio de tabla personalizado a través de la configuración. Pero esta configuración solo se puede usar cuando se inicializa el sistema (al crear el directorio de datos), una vez que se completa la inicialización, no se puede volver a cambiar. Echemos un vistazo a los parámetros de inicio relevantes:

  • Al innodb_undo_directoryespecificar undoel directorio donde se encuentra el espacio de tabla, si no se especifica este parámetro, el directorio predeterminado undodonde se encuentra el espacio de tabla es el directorio de datos.

  • Definiendo el número de tablespaces innodb_undo_tablespaces. undoEl valor predeterminado de este parámetro es 0, lo que indica que no undose crea ningún espacio de tablas.

    Los segmentos de reversión n.º 33~127 se pueden distribuir uniformemente en diferentes espacios de tablas de deshacer.

小提士:
Si especificamos crear el tablespace de deshacer cuando se inicializa el sistema, entonces el segmento de reversión No. 0 en el tablespace del sistema no estará disponible.

Por ejemplo, cuando inicializamos el sistema, especificamos como innodb_rollback_segments, de modo que los segmentos No. y No. rollback se distribuirán a un espacio de tabla respectivamente .35innodb_undo_tablespaces23334undo

undo表空间Uno de los beneficios de la configuración es que cuando el undoarchivo en el espacio de la tabla es lo suficientemente grande, se puede convertir automáticamente en un archivo pequeño. El tamaño del espacio de la tabla del sistema solo se puede aumentar continuamente, pero no se puede truncar.undo表空间截断truncate

Supongo que te gusta

Origin blog.csdn.net/liang921119/article/details/130905213
Recomendado
Clasificación