Este artículo lo lleva a comprender la estructura de registro InnoDB de MySQL [Parte 2]

prefacio

El artículo anterior decía que InnoDB tiene Compact, Redundant, Dynamicy Compressed4formatos de fila. Habla principalmente del Compactformato de fila, que se compone de dos partes principales: información adicional registrada y datos reales registrados. Se recomienda leer el artículo anterior y el artículo anterior. Si es importante Diga [ through train ] tres veces, no se salte el capítulo. Hoy entendemos principalmente los tres formatos de fila restantes y el desbordamiento de datos de fila

1. Formato de fila redundante

El formato de fila redundante es un formato de fila utilizado antes de MySQL 5.0, lo que significa que es muy antiguo, pero aún quiero mencionarlo desde la perspectiva del aprendizaje, y todos pueden entenderlo.El formato de fila redundante como se muestra en la imagen:

inserte la descripción de la imagen aquí
Para un mejor aprendizaje, creamos una demo3tabla aquí y agregamos dos datos

mysql> create table demo3( c1 varchar(10), c2 varchar(10) not null, c3 char(10), c4 varchar(10), c5 varchar(1024)) charset=ascii row_format=Redundant;
Query OK, 0 rows affected (0.02 sec)

mysql> insert into demo3 values('aaaaa','bbbb','ccc','dd','e');
Query OK, 1 row affected (0.00 sec)

mysql> insert into demo3 values('eeeee','ffff',null,null,'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdeefghijklmnopqrstuvwxyz');
Query OK, 1 row affected (0.00 sec)

Los registros en la tabla ahora se ven así

mysql> select * from demo3;
+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------+
| c1    | c2   | c3   | c4   | c5                                                                                                                                 |
+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------+
| aaaaa | bbbb | ccc  | dd   | e                                                                                                                                  |
| eeeee | ffff | NULL | NULL | abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz |
+-------+------+------+------+------------------------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)

Echemos un vistazo a las diferencias en el formato de línea redundante desde varios aspectos.

1.1 Lista de compensaciones de longitud de campo

CompactEl comienzo del formato de línea es una lista de longitud de campo de longitud variable, y Redundantel comienzo del formato de línea es una lista de desplazamiento de longitud de campo, que es diferente de la lista de longitud de campo de longitud variable de dos maneras:

  • No hay 变长dos palabras, es decir, el formato de fila redundante almacenará la información de longitud de todas las columnas (incluidas las columnas ocultas) en el registro en orden inverso a la lista de compensación de longitud de campo
  • Hay dos 偏移palabras más, lo que significa que el método de cálculo de la longitud es diferente del formato de fila compacto, que no es tan intuitivo, utiliza la diferencia entre números adyacentes para calcular la longitud de cada columna.

Por ejemplo, la primera fila de datos, intentemos analizarla:

La longitud de la primera columna row_ides de 6 bytes, es decir, la longitud de 0x06
la segunda columna trx_ides de 6 bytes, un total de 12 bytes, es decir, la longitud de 0x0c
la tercera columna roll_pointeres de 7 bytes, un total de 19 bytes, también Eso es decir, la longitud de 0x13
la cuarta columna C1es de 5 bytes, un total de 24 bytes, es decir, la longitud de 0x18
la quinta columna C2es de 4 bytes, un total de 28 bytes, es decir, la longitud de 0x1c
la sexta columna C3es de 10 bytes, Un total de 38 bytes, es decir, la longitud de 0x26
la séptima columna C4es de 2 bytes, un total de 40 bytes, es decir, la longitud de 0x28
la octava columna C5es de 1 byte, un total de 41 bytes, es decir0x29

El efecto de la descarga de orden inverso es: 29 28 26 1c 18 13 0c 06, complete los datos como se muestra en la figura

inserte la descripción de la imagen aquí
Abrimos directamente demo3.ibdel archivo para verlo

inserte la descripción de la imagen aquí

1.2 Información del encabezado del registro

La información del encabezado del registro en formato de fila redundante consiste en bytes 6 y bits binarios 48. Los significados de estos bits binarios son los siguientes:

nombre tamaño (unidad: bit) describir
bit reservado 1 1 no utilizado
reservado 2 1 no utilizado
eliminar_mascarilla 1 Marcar si se elimina el registro
min_rec_mask 1 Esta marca se agregará al registro más pequeño en cada nodo que no sea hoja del árbol B+
n_propiedad 4 Indica el número de registros que posee el registro actual
heap_no 13 Indica la información de posición del registro actual en el montón de registros
n_campo 10 Indica el número de columnas en el registro
1byte_offs_bandera 1 Si el desplazamiento correspondiente a cada columna en la lista de desplazamiento de longitud de campo de etiqueta está representado por 1 byte o 2 bytes
próximo_registro dieciséis Indica la posición relativa del siguiente registro

La primera línea de información del encabezado del registro es:00 00 10 11 00 ca

inserte la descripción de la imagen aquíConvirtamos el registro anterior de hexadecimal a binario e intentemos analizarlo.

00000000 00000000 00010000 00010001 00000000 11001010

De acuerdo con estos datos binarios, la siguiente información se puede obtener dividiendo los datos de acuerdo con la estructura del encabezado del registro

Bit reservado 1: 0
Bit reservado 2: 0
delete_mask: 0
min_rec_mask: 0
n_owned: 0000
heap_no: 00000000 00010 (2)
n_field: 000 0001000 (8)
1byte_offs_flag: 1 (1)
next_record: 00000000 1100101 0 (202)

En comparación con la información del encabezado del registro en el formato de línea compacta, existen dos diferencias:

  • El formato de fila redundante tiene dos atributos más: n_field y 1byte_offs_flag;
  • El formato de fila redundante no tiene el atributo record_type.

1.4 Cómo elegir el valor de 1byte_offs_flag

Dijimos anteriormente que el desplazamiento correspondiente a cada columna puede ocupar 1 byte o 2 bytes para el almacenamiento, entonces, ¿cuándo usar 1 byte y cuándo usar 2 bytes? De hecho, se juzga según el tamaño total de los datos reales registrados en el formato de fila Redundante:

  • Cuando el número de bytes que ocupan los datos reales registrados es menor o igual a 127 (hexadecimal 0x7f, binario 01111111), el desplazamiento correspondiente a cada columna ocupa 1 byte

  • Cuando el número de bytes que ocupan los datos reales registrados es superior a 127 pero no superior a 32767 (hexadecimal 0x7fff, binario 0111111111111111), el desplazamiento correspondiente a cada columna ocupa 2 bytes

  • Cuando los datos reales del registro son mayores a 32767, el registro en este momento se ha almacenado en la página de desbordamiento, y solo los primeros 768 bytes y la dirección de la página de desbordamiento de 20 bytes están reservados en esta página (por supuesto, en estos 20 bytes También se registra otra información). Debido a que la lista de compensación de longitud de campo solo necesita registrar la compensación de cada columna en esta página, es suficiente que cada columna use 2 bytes para almacenar la compensación.

Para saber si el desplazamiento de cada columna está representado por 1 byte o 2 bytes al analizar registros, el formato de fila redundante coloca deliberadamente un atributo llamado 1byte_offs_flag en la información del encabezado del registro:

  • Cuando su valor es 1, indica que se utiliza 1 byte para el almacenamiento
  • Cuando su valor es 0, indica que se utilizan 2 bytes para el almacenamiento

1.5 Manejo de valores NULL en el formato de fila Redundante

Debido a que el formato de fila redundante no tiene una lista de valores NULL, el formato de fila redundante realiza un procesamiento especial en los desplazamientos correspondientes a cada columna en la lista de desplazamiento de longitud de campo: el primer bit del valor de desplazamiento correspondiente a la columna Como base si es NULL, este bit también puede denominarse bit NULL. Es decir, al analizar una columna de un registro, primero verifique si el bit NULL del desplazamiento correspondiente a la columna es 1, si es 1, entonces el valor de la columna es NULL, de lo contrario, no es NULL.

Esto también explica por qué siempre que el dato real registrado anteriormente sea mayor a 127 (hexadecimal 0x7f, binario 01111111), se utilizan 2 bytes para representar el desplazamiento correspondiente a una columna, principalmente el primer bit es el llamado bit NULL, utilizado para marcar si el valor de la columna es NULL.

Pero hay otro punto a tener en cuenta, para una columna con un valor NULL, si el tipo de columna es un tipo de longitud fija determina el método de almacenamiento real del valor NULL:

  • Si el campo que almacena el valor NULL es de tipo de longitud fija, como el tipo de datos CHAR(M), el valor NULL también ocupará la parte de datos reales del registro, y los datos correspondientes a este campo se completarán con 0x00 bytes. .
  • Si el campo que almacena el valor NULL es de tipo de datos de longitud variable, no se ocupará ningún espacio de almacenamiento en los datos reales del registro.

Además de los puntos anteriores, el formato de línea redundante y el formato de línea compacta son aproximadamente iguales

Intentemos analizar el segundo dato (el número de bytes que ocupan los datos reales es superior a 127):

La longitud de la primera columna row_ides de 6 bytes, es decir, la longitud de 0x00 0x06
la segunda columna trx_ides de 6 bytes, un total de 12 bytes, es decir, la longitud de 0x00 0x0c
la tercera columna roll_pointeres de 7 bytes, un total de 19 bytes, también Eso es decir, la longitud de 0x00 0x13
la cuarta columna C1es de 5 bytes, un total de 24 bytes, es decir, la longitud de 0x00 0x18
la quinta columna C2es de 4 bytes, un total de 28 bytes, es decir, la longitud de 0x00 0x1c
la sexta columna C3es de 10 bytes, Un total de 38 bytes, es decir 0x00 0x26, pero el valor es NULL, 最高位标识1después de eso, el valor de 0x80 0x26
la séptima columna C4es NULL, un total de 38 bytes, es decir, la longitud de 0x80 0x26
la octava columna C5es de 130 bytes, un total de 168 Festival de personajes, es decir0x00 0xa8

Abrimos directamente el archivo demo3.ibd para ver si es correcto:

inserte la descripción de la imagen aquíAdemás de los puntos anteriores, el formato de línea redundante y el formato de línea compacta son aproximadamente iguales.

1.6 Formato de almacenamiento de la columna CHAR(M)

Sabemos que el formato de fila Compacto es bastante problemático cuando se almacenan datos en columnas de tipo CHAR(M), se divide en juegos de caracteres de longitud variable y juegos de caracteres de longitud fija, pero es muy simple en el formato de fila Redundante, independientemente de los caracteres utilizados en la columna ¿Cuál es el conjunto, siempre que se utilice el tipo CHAR(M), el espacio de datos real ocupado es el producto del número máximo de bytes requerido por el conjunto de caracteres para representar un carácter y M. Por ejemplo, el espacio de datos real ocupado por una columna de tipo CHAR(10) que usa el juego de caracteres utf8 siempre es de 30 bytes, y el espacio de datos real ocupado por una columna de tipo CHAR(10) que usa el juego de caracteres gbk es siempre de 20 bytes. Se puede ver a partir de esto que la columna de tipo CHAR(M) que usa el formato de fila Redundante no generará fragmentación.

2. Desbordamiento de datos de fila

2.1 Los datos máximos que VARCHAR(M) puede almacenar

Sabemos que una columna de tipo VARCHAR(M) puede ocupar hasta 65535 bytes. Entre ellos, M representa el número máximo de caracteres almacenados en este tipo.Si usamos el conjunto de caracteres ASCII, un carácter representa un byte.Veamos si VARCHAR(65535) está disponible

mysql> create table demo4 (c varchar(65535)) charset=ascii row_format=compact;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

Se puede ver en el mensaje de error que MySQL tiene un límite en el espacio de almacenamiento máximo ocupado por un registro. Excepto por columnas de tipo BLOB o TEXT, los bytes ocupados por todas las demás columnas (excluyendo columnas ocultas e información de encabezado de registro) El total la longitud no puede exceder los 65535 bytes. Entonces, el servidor MySQL sugiere que cambiemos el tipo de almacenamiento a TEXT o BLOB. Además de los datos de la columna en sí, estos 65535 bytes también incluyen algunos otros datos (sobrecarga de almacenamiento).Por ejemplo, para almacenar una columna de tipo VARCHAR(M), en realidad necesitamos ocupar 3 partes de espacio de almacenamiento:

  • datos reales
  • Los datos reales ocupan la longitud del byte (pueden ocupar dos bits)
  • Identificación de valor NULL, si la columna no tiene el atributo NOT NULL (un bit), solo se pueden almacenar 65532 bytes de datos como máximo
mysql> create table demo4 (c varchar(65532)) charset=ascii row_format=compact;
Query OK, 0 rows affected (0.06 sec)

Si la columna de tipo VARCHAR(M) no utiliza el conjunto de caracteres ASCII, el valor máximo de M depende del número máximo de bytes requerido por el conjunto de caracteres para representar un carácter. En el caso de que se permita que el valor de la columna sea NULL, el juego de caracteres gbk indica que un carácter requiere como máximo 2 bytes, luego, bajo este juego de caracteres, el valor máximo de M es 32766 (es decir: 65532/2) , es decir Puede almacenar hasta 32766 caracteres, el juego de caracteres utf8 significa que un carácter necesita hasta 3 bytes, por lo que bajo este juego de caracteres, el valor máximo de M es 21844, lo que significa que puede almacenar hasta 21844 ( es decir: 65532/3) carácter.

2.2 Desbordamiento causado por demasiados datos en el registro

Hagamos una prueba con asciiuna demo4tabla de conjuntos de caracteres e insertemos un dato:

mysql> insert into demo4 values(repeat('a',65532));
Query OK, 1 row affected (0.02 sec)

Sugerencia:
REPEAT('a', 65532) es una llamada de función, lo que significa generar una cadena que repite el carácter 'a' 65532 veces

Como se mencionó anteriormente, la unidad básica de interacción entre el disco y la memoria en MySQL es la página, es decir, MySQL usa la página como la unidad básica para administrar el espacio de almacenamiento, y nuestros registros se asignarán a una determinada página para su almacenamiento. El tamaño de una página es generalmente de 16 KB, que son 16384 bytes, y un VARCHAR(M)tipo de columna puede almacenar hasta 65532 bytes, lo que puede causar una situación embarazosa en la que una página no puede almacenar un registro.

En los formatos de fila Compacto y Reduntante, para una columna que ocupa un gran espacio de almacenamiento, solo una parte de los datos de la columna se almacenarán en los datos reales del registro, y los datos restantes se dispersarán y almacenarán en varios otros. páginas, y luego los datos reales del registro. El lugar de datos utiliza 20 bytes para almacenar las direcciones que apuntan a estas páginas (por supuesto, estos 20 bytes también incluyen el número de bytes ocupados por los datos dispersos en otras páginas), de modo que el Se puede encontrar la página donde se encuentran los datos restantes, como la que se muestra en la figura:

inserte la descripción de la imagen aquí
Como se puede ver en la figura, para los formatos de fila Compacto y Reduntante, si hay muchos datos en una columna, solo los primeros 768 bytes de datos en la columna y un puntero a otras columnas se almacenarán en los datos reales de este registro. La dirección de la página, y luego almacenar los datos restantes en otras páginas. Este proceso también se denomina desbordamiento de página, y aquellas páginas que almacenan más de 768 bytes también se denominan páginas de desbordamiento.

Finalmente, debe tenerse en cuenta que no solo las columnas de tipo VARCHAR(M), sino también las columnas de otros tipos TEXT y BLOB se desbordarán al almacenar una gran cantidad de datos.

Tres, el punto crítico de desbordamiento de línea.

¿Cuál es el punto crítico donde ocurre el desbordamiento de fila? En otras palabras, el desbordamiento de filas ocurre cuando la columna almacena ¿cuántos bytes de datos?

MySQL estipula que se deben almacenar al menos dos filas de registros en una página. Además de almacenar nuestros registros, cada página también necesita almacenar información adicional. La información extra desordenada debe agregar hasta 132 bytes de espacio (ahora solo necesito saber este número. ok), el resto del espacio se puede usar para almacenar registros.

La información adicional requerida para cada registro es de 27 bytes.

  • 2 bytes se utilizan para almacenar la longitud de los datos reales
  • 1 byte se usa para almacenar si la columna es un valor NULL
  • 5 bytes de información de encabezado
  • 6 bytes para la columna DB_ROW_ID
  • 6 bytes para la columna DB_TRX_ID
  • 7 bytes para la columna DB_ROLL_PTR

Suponiendo que el número de bytes de datos almacenados en una columna es n, MySQL estipula que si la columna no se desborda, debe satisfacer la siguiente fórmula:

132 + 2×(27 + n) < 16384

Resolviendo esta fórmula se obtiene la solución: n < 8099. Es decir, si los datos almacenados en una columna tienen menos de 8099 bytes, la columna no se convertirá en una columna de desbordamiento; de lo contrario, la columna deberá convertirse en una columna de desbordamiento. Sin embargo, la conclusión de 8099 bytes es solo para una demo4tabla con una sola columna. Si hay varias columnas en la tabla, la fórmula anterior y la conclusión deben cambiarse, por lo que el punto es: no necesita prestar atención a este crítico Cuál es el punto, solo sepa que si los datos almacenados en una columna de nuestro registro ocupan muchos bytes, la columna puede convertirse en una columna de desbordamiento.

Formato de cuatro líneas, DINÁMICO y COMPRIMIDO

A continuación, se presentarán los otros dos formatos de fila Dynamicy Compressedel formato de fila. La versión de MySQL que estoy usando ahora es 8.0 y su formato de fila predeterminado es Dinámico.

mysql> show variables like '%innodb_default_row_format%';
+---------------------------+---------+
| Variable_name             | Value   |
+---------------------------+---------+
| innodb_default_row_format | dynamic |
+---------------------------+---------+
1 row in set (0.04 sec)

mysql> set persist innodb_default_row_format = 'dynamic';
Query OK, 0 rows affected (0.01 sec)

Estos dos formatos de línea son similares al formato de línea compacto, pero son un poco diferentes cuando se trata de datos de desbordamiento de fila. No almacenarán los primeros 768 bytes de los datos reales del campo en los datos reales del registro, sino que almacenarán todos los bytes Todos se almacenan en otras páginas, y solo las direcciones de otras páginas se almacenan en los datos reales registrados.

La diferencia entre el formato de fila comprimido y dinámico es que el formato de fila comprimido utiliza un algoritmo de compresión para comprimir la página y ahorrar espacio.

Resumir

Estos dos artículos tienen mucho conocimiento teórico, jaja, pero afortunadamente no se usan mucho en el trabajo, es bueno que todos conozcan estos términos, porque en la explicación de MVCC más adelante, también usaremos algunos términos profesionales en este artículo InnoDB define 4 formatos de fila, y la estructura de registro de cada formato de fila es diferente. Al mismo tiempo, también hemos aprendido sobre los métodos de almacenamiento de tipos de datos de longitud fija y variable en la estructura de registro y el desbordamiento de fila. Vamos concluir

  • La página es la unidad básica de interacción entre disco y memoria en MySQL, y también la unidad básica de MySQL para administrar el espacio de almacenamiento.

  • InnoDB actualmente define formatos de 4 filas:

    • Formato de fila COMPACTO:
      inserte la descripción de la imagen aquí
    • Formato de fila REDUNDANTE:

    inserte la descripción de la imagen aquí

    • Formatos de fila DINÁMICA y COMPRIMIDA:

      Los formatos de fila Dinámico y Comprimido son similares al formato de fila COMPACTO, y son un poco diferentes cuando se trata de datos de desbordamiento de fila. No almacenan los primeros 768 bytes de los datos reales del campo en los datos reales del registro, pero almacenan todos los bytes Para otras páginas, solo almacene la dirección de otras páginas en los datos reales del registro

  • Formato de fila COMPACTO Para columnas de tipo CHAR(M), cuando la columna utiliza un conjunto de caracteres de longitud fija, el número de bytes ocupados por la columna no se agregará a la lista de longitud de campo de longitud variable, y si la longitud variable se utiliza el conjunto de caracteres, el número de bytes ocupados por la columna también se agregará a la lista de longitud de campo de longitud variable.

  • En el caso de que se permita que el valor de la columna sea NULL, el valor máximo de M bajo el juego de caracteres gbk es 32766, y el valor máximo de M bajo el juego de caracteres utf8 es 21844. Todo esto es solo en el caso de un campo en la tabla ¡Asegúrese de recordar que la longitud total de bytes ocupados por todas las columnas en una fila (excluyendo las columnas ocultas y la información del encabezado del registro) no puede exceder los 65535 bytes!

  • Cuando hay demasiados datos en el registro y no caben en la página actual, los datos sobrantes se almacenarán en otras páginas.Este fenómeno se denomina desbordamiento de fila. En los formatos de fila Compacto y Redundante, para columnas que ocupan un gran espacio de almacenamiento, solo una parte de los datos de la columna se almacenará en los datos reales registrados, y los datos restantes se dispersarán y almacenarán en varias otras páginas, y luego, los 20 bytes de datos reales registrados se utilizan para almacenar direcciones que apuntan a estas páginas.

  • El punto crítico del desbordamiento de fila: si los datos almacenados en una columna tienen menos de 8099 bytes, entonces la columna no se convertirá en una columna de desbordamiento; de lo contrario, la columna debe ser una columna de desbordamiento. Sin embargo, la conclusión de 8099 bytes es solo para una tabla con una sola columna. Si hay varias columnas en la tabla, la conclusión será inconsistente, por lo que el punto es: no es necesario que preste atención a cuál es el punto crítico. Es decir, solo sepa que si cuando los datos almacenados en una columna de un registro ocupan una cantidad muy alta de bytes, la columna puede convertirse en una columna de desbordamiento.

  • Las columnas del tipo CHAR(M) del juego de caracteres de longitud variable requieren al menos M bytes, mientras que VARCHAR(M) no tiene este requisito. Por ejemplo, para una columna CHAR(10) que utiliza el conjunto de caracteres utf8, la longitud de los datos almacenados en la columna oscila entre 10 y 30 bytes. Incluso si almacenamos una cadena vacía en esta columna, ocupará 10 bytes. Esto se debe a que la longitud en bytes del valor actualizado en el futuro es mayor que la longitud en bytes del valor original y menos de 10 bytes. El registro es actualizado directamente en lugar de reasignar un nuevo espacio de registro en el espacio de almacenamiento, lo que hace que el espacio de registro original se convierta en la denominada fragmentación

Cuando terminé de aprender esta parte del conocimiento, admiré la profundidad de la investigación del autor, aunque los puntos del conocimiento son muchos, difíciles y complicados, la forma en que el autor combina imágenes y textos nos permite entenderlo bien.

Hasta ahora, el estudio de hoy ha terminado, espero que te conviertas en un yo indestructible
~~~

No puedes conectar los puntos mirando hacia adelante; solo puedes conectarlos mirando hacia atrás. Así que tienes que confiar en que los puntos se conectarán de alguna manera en tu futuro. Tienes que confiar en algo: tu instinto, destino, vida, karma, lo que sea. Este enfoque nunca me ha defraudado y ha marcado una gran diferencia en mi vida.

Si mi contenido te es útil, por favor 点赞, 评论,, 收藏la creación no es fácil, el apoyo de todos es la motivación para que yo persevere

inserte la descripción de la imagen aquí

Supongo que te gusta

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