Este artículo lo lleva a comprender el espacio de tabla InnoDB de MySQL

prefacio

A través del contenido anterior, creo que todos saben que el espacio de tabla es un concepto abstracto, para el espacio de tabla del sistema, corresponde al 一个或多个archivo real en el sistema de archivos, para cada espacio de tabla independiente, corresponde a 一个la tabla nombrada en el archivo system.nombre .ibddel archivo real.

Puede pensar en el espacio de tablas como un grupo dividido en muchas páginas.Cuando queremos insertar un registro para una tabla determinada, sacamos una página correspondiente del grupo y escribimos los datos en ella.

El contenido de este capítulo profundizará en los detalles del espacio de tablas y lo llevará a nadar en la piscina de la estructura de almacenamiento de InnoDB. Ya que habrá más conceptos involucrados en este capítulo, aunque estos conceptos no son difíciles, dependen unos de otros, por lo que te aconsejo que leas:不要跳着看

1. Recuerda algunos conocimientos antiguos

1.1 Tipos de páginas

Permítanme enfatizar aquí nuevamente que InnoDB administra el espacio de almacenamiento en unidades.Nuestro índice agrupado (es decir, datos completos de la tabla) y otros índices secundarios se guardan en el espacio de la tabla en forma de árbol B+, y B+ Los nodos del árbol son datos paginas Como dijimos anteriormente, el nombre de tipo de esta página de datos es en realidad: fil_page_index. Además de este tipo de página para almacenar datos de índice, InnoDB también diseña varios tipos diferentes de páginas para diferentes propósitos.Creo que debe estar familiarizado con la siguiente tabla:

escribe un nombre hexadecimal describir
fil_page_type_allocated 0x0000 última asignación, aún no utilizada
fil_page_undo_log 0x0002 deshacer página de registro
fil_page_inode 0x0003 nodo de información del segmento
fil_page_ibuf_free_list 0x0004 insertar lista libre de búfer
file_page_ibuf_mapa de bits 0x0005 insertar mapa de bits de búfer
fil_page_type_sys 0x0006 página del sistema
fil_page_type_trx_sys 0x0007 datos del sistema transaccional
fil_page_type_fsp_hdr 0x0008 Información del encabezado del espacio de tabla
fil_page_type_xdes 0x0009 Página de descripción extendida
fil_page_type_blob 0x000a página de desbordamiento
fil_page_index 0x45bf Páginas de índice, también conocidas como páginas de datos

Debido a que hay un prefijo de fil_pageo delante del tipo de página fil_page_type, en aras de la simplicidad, omitiremos estos prefijos cuando expliquemos el tipo de página más adelante. Por ejemplo, fil_page_type_allocatedel tipo se llama allocatedtipo y fil_page_indexel tipo se llama indextipo, etc.

1.2 Partes comunes de la página

Dijimos MySQL之数据页结构en el artículo anterior que la página de datos, es decir, indexla página tipo consta de 7 partes, dos de las cuales son comunes a todos los tipos de páginas (por supuesto, no espero que recuerdes lo que dije, así que de nuevo aquí) Cualquier tipo de página tiene la siguiente estructura general:

inserte la descripción de la imagen aquí
Como puede ver en la imagen de arriba, cualquier tipo de página contendrá estas dos secciones:

  • File Header:Alguna información general sobre la página de registro
  • File Trailer:Verifique la integridad de la página para garantizar la consistencia del contenido cuando se actualice de la memoria al disco.

Para File Trailerno enfatizar demasiado, enfatizaremos los File Headerdiversos componentes nuevamente aquí:

nombre Tamaño (unidad: B) describir
fil_page_space_or_chksum 4 Suma de verificación de página (valor de suma de verificación)
fil_page_offset 4 número de página
página_archivo_prev 4 número de página de la página anterior
fil_pagina_siguiente 4 Número de página de la página siguiente
fil_page_lsn 8 La posición de la secuencia de registro correspondiente cuando se modificó la página por última vez (el nombre en inglés es: número de secuencia de registro)
fil_page_type 2 tipo de página
fil_page_file_flush_lsn 8 Solo se define en una página del espacio de tabla del sistema, lo que significa que el archivo se ha actualizado al menos al valor lsn correspondiente
fil_page_arch_log_no_or_space_id 4 a qué tablespace pertenece la página

Ahora, a excepción de los dos campos con LSN en el nombre que quizás no entienda, los otros campos deben ser muy familiares, pero aún queremos enfatizar los siguientes puntos:

  • Cada página en el espacio de tablas corresponde a un número de página, es decir fil_page_offset, el número de página consta de 4 bytes, es decir, 32 bits, por lo que un espacio de tablas puede tener un máximo de 2³²páginas, si de acuerdo con el tamaño predeterminado de la página 16kb es la cantidad máxima 64tbde datos admitida por un espacio de tablas. El número de página de la primera página del espacio de tabla es 0, y los números de página subsiguientes son 1, 2, 3... y así sucesivamente.

  • Algunos tipos de páginas pueden formar una lista enlazada, y las páginas de la lista enlazada no se pueden almacenar en orden físico, sino que almacenan los números de página de la página anterior y la página siguiente según la fil_page_prevsuma fil_page_next. Cabe señalar que estos dos campos son principalmente para indexlos tipos de páginas, es decir, las páginas de datos de las que hemos estado hablando antes se utilizan para establecer una lista doblemente enlazada para cada capa de nodos después de establecer el árbol B+. de las páginas no utilizan estos dos campos

  • El tipo de cada página se fil_page_typeindica, por ejemplo, el valor de este campo de una página de datos es 0x45bf, presentaremos varios tipos de páginas más adelante, y diferentes tipos de páginas tienen diferentes valores en este campo

Dos mesas independientes

Sabemos que InnoDB admite muchos tipos de espacios de tabla y este artículo se centra en la estructura de 独立表空间y 系统表空间. Sus estructuras son relativamente similares, pero dado que el espacio de tabla del sistema contiene información adicional sobre todo el sistema, primero presentaremos un espacio de tabla independiente más simple y hablaremos sobre la estructura del espacio de tabla del sistema más adelante.

2.1 El concepto de Extensión

Hay demasiadas páginas en el espacio de tablas 为了更好的管理这些页面e InnoDB propone extentel concepto de área (nombre en inglés: ). Para una página de 16 KB, las páginas consecutivas 64son un área, es decir, un área ocupa el 1MBtamaño de espacio predeterminado. Tanto si se trata de un espacio de tablas del sistema como de un espacio de tablas independiente, se puede considerar que se compone de varias áreas 每256个区被划分成一组. Haz un dibujo para mostrar que es así:

inserte la descripción de la imagen aquí
Entre ellos , extent 0 ~ extent 255se cuentan estos 256 distritos 第一个组, extent 256 ~ extent 511se cuentan estos 256 distritos 第二个组, y extent 512 ~ extent 767se cuentan estos 256 distritos 第三个组(la figura anterior no dibuja todos los distritos del tercer grupo, por favor tome una decisión), y así sucesivamente, más grupos Puede ser dividido. Las primeras páginas de estos grupos son de tipo similar, por ejemplo:

inserte la descripción de la imagen aquí
De la figura anterior podemos conocer la siguiente información:

  • 第一个组最开始的3个页面的类型是固定的, es decir, los tipos de las tres primeras páginas en el área de extensión 0 son fijos, y son:

    • FSP_HDR类型:Este tipo de página se utiliza para registrar 表空间的一些整体属性以及本组所有的区las propiedades de las 256 áreas completas, a saber, extensión 0 ~ extensión 255. Una cosa a tener en cuenta es que todo el tablespace solo está disponible 一个FSP_HDR类型的页面.
    • IBUF_BITMAP类型:Este tipo de página es 本组所有的区的所有页面关于INSERT BUFFERinformación almacenada.
    • INODE类型:Este tipo de página almacena una serie de INODEestructuras de datos denominadas .
  • Para el resto 最开始的2个页面的类型是固定de grupos, es decir, se fijan los tipos de las dos primeras páginas de extensión 256 y extensión 512, respectivamente:

    • XDES类型:El nombre completo es Extent Descriptor, 用来登记本组256个区的属性es decir, para este tipo de página en la extensión 256, los atributos de estas áreas se almacenan en la extensión 256 ~ extensión 511, y para este tipo de página en la extensión 512, se almacena en la extensión 512 ~ extensión 767 propiedades de estas áreas. La página de tipo FSP_HDR presentada anteriormente es similar a la página de tipo XDES, excepto que la página de tipo FSP_HDR almacenará además algunos atributos de espacio de tabla.
    • IBUF_BITMAP类型:Igual que arriba, no hay más explicación aquí.

La estructura macro es así, y no es necesario que memorice los sustantivos con demasiada claridad, siempre que recuerde aproximadamente:表空间被划分为许多连续的区,每个区默认由64个页组成,每256个区划分为一组,每个组的最开始的几个页面类型是固定的就好了

2.2 El concepto de segmento (Segmento)

Si la cantidad de datos en nuestra tabla es pequeña, como si solo hay docenas o cientos de datos en su tabla, el concepto de área no es necesario, porque los datos correspondientes se pueden almacenar en unas pocas páginas simples, pero en la etapa posterior, no puede retener más y más registros en la tabla.

Teóricamente hablando, usar solo el concepto de página sin introducir el concepto de área no tiene ningún efecto sobre el funcionamiento del motor de almacenamiento, pero consideremos el siguiente escenario:

  • Cada vez que insertamos un registro en la tabla, esencialmente insertamos datos en la tabla 聚簇索引y 所有二级索引los nodos del árbol B+ representado. Y las páginas en cada capa del árbol B+ formarán una lista doblemente enlazada, si es así 以页为单位来分配存储空间的话,双向链表相邻的两个页之间的物理位置可能离得非常远. Cuando introdujimos los escenarios aplicables del índice de árbol B+ 范围查询只需要定位到最左边的记录和最右边的记录, mencionamos específicamente que es suficiente escanear a lo largo de la lista doblemente enlazada, y si hay dos páginas adyacentes en la lista enlazada 物理位置离得非常远, es la llamada 随机I/O.

Sugerencia:
la velocidad del disco es diferente en varios órdenes de magnitud a la velocidad de la memoria, y la E/S aleatoria es muy lenta, por lo que debemos tratar de hacer que las posiciones físicas de las páginas adyacentes en la lista enlazada sean adyacentes entre sí. de modo que solo cuando se realizan consultas de rango se pueden usar las llamadas E/S secuenciales.

Por eso se introdujo el concepto de extensión 一个区就是在物理位置上连续的64个页(1M). Cuando la cantidad de datos en la tabla es grande, al asignar espacio para un índice, ya no se asigna en unidades de páginas, sino en unidades de regiones Incluso cuando los datos en la tabla son muy, muy grandes, pueden ser asignados a la vez Asignar varias regiones contiguas. Aunque puede causar un pequeño desperdicio de espacio (los datos son insuficientes para llenar toda el área), desde el punto de vista del rendimiento, puede eliminar una gran cantidad de E/S aleatorias, y las ventajas superan las desventajas.

La consulta de rango que mencionamos es en realidad 对B+树叶子节点中的记录进行顺序扫描, y si no distingue entre los nodos de hoja y los nodos que no son de hoja, y coloca todas las páginas representadas por los nodos en el área aplicada, el efecto del escaneo de rango se reducirá considerablemente. Entonces, InnoDB trata los nodos hoja y los nodos no hoja del árbol B+ de manera diferente, es decir 叶子节点有自己独有的区, 非叶子节点也有自己独有的区. 存放叶子节点的区的集合就算是一个段(segment),存放非叶子节点的区的集合也算是一个段. eso 一个索引会生成2个段,一个叶子节点段,一个非叶子节点段es

De manera predeterminada, una tabla que usa el motor de almacenamiento InnoDB tiene solo un índice agrupado, y un índice generará 2 segmentos, y un 段是以区为单位申请存储空间área ocupa 1M de espacio de almacenamiento de manera predeterminada, por lo que, de manera predeterminada, una tabla pequeña con solo unos pocos registros también necesita 2M ¿Espacio de almacenamiento? ¿Debo solicitar 2 millones más de espacio de almacenamiento cada vez que agregue un índice en el futuro?

Esto es simplemente un gran desperdicio para las tablas que almacenan menos registros. InnoDB es bastante frugal y, por supuesto, esta situación se tiene en cuenta. El quid de este problema es que las áreas que hemos introducido hasta ahora son todas muy puras, es decir, un área está completamente asignada a un determinado segmento, o todas las páginas de un área existen para almacenar los datos del mismo segmento. los datos del segmento no llenan todas las páginas de la zona, las páginas restantes no se pueden utilizar para otros fines. Ahora, para considerar el hecho de que asignar un determinado segmento en unidades de un área completa es un desperdicio de espacio de almacenamiento para una tabla con una pequeña cantidad de datos, InnoDB propone que en un 一个碎片(fragment)区的概念área fragmentada, no todas las páginas son para The existen datos del mismo segmento, pero las páginas en el área fragmentada se pueden usar para diferentes propósitos. Por ejemplo, algunas páginas se usan para el segmento A, algunas páginas se usan para el segmento B y algunas páginas ni siquiera pertenecen a ningún segmento . El área fragmentada pertenece directamente al espacio de tabla y no pertenece a ningún segmento. Entonces, la estrategia para asignar espacio de almacenamiento para un determinado segmento es la siguiente:

  • Al comienzo de la inserción de datos en la tabla, el segmento asigna espacio de almacenamiento en unidades de una sola página desde un área fragmentada

  • 当某个段已经占用了32个碎片区页面之后, el espacio de almacenamiento se asignará en unidades de áreas completas

Entonces, ahora un segmento no puede definirse simplemente como una colección de ciertas áreas, sino que, de manera más precisa, debe ser una colección de algunas páginas dispersas y algunas áreas completas. Además de los segmentos de nodos de hoja y los segmentos de nodos que no son de hoja del índice, InnoDB también tiene segmentos definidos para almacenar algunos datos especiales, como segmentos de reversión. Por supuesto, no nos importan otros tipos de segmentos ahora, y ahora solo necesitamos saber Un segmento es una colección de páginas fragmentadas así como secciones completas.

2.3 Clasificación de zonas

El espacio de la mesa se compone de varias áreas, que se pueden dividir aproximadamente en 4 tipos:

  • 空闲的区:Actualmente no se utilizan páginas en esta zona.

  • 有剩余空间的碎片区:Indica que todavía hay páginas disponibles en el área fragmentada.

  • 没有剩余空间的碎片区:Indica que se utilizan todas las páginas del área fragmentada y que no hay páginas libres.

  • 附属于某个段的区:Cada índice se puede dividir en segmentos de nodo hoja y segmentos de nodo no hoja. Además, InnoDB también definirá algunos segmentos de propósito especial. Cuando la cantidad de datos en estos segmentos es grande, el área se utilizará como unidad de asignación básica. . .

Estos 4 tipos de zonas también pueden denominarse los 4 estados de la zona. InnoDB define sustantivos específicos para estos 4 estados de zonas:

nombre del Estado significado
gratis Área libre
libre_frag Área fragmentada con espacio libre
fragmento_completo Área fragmentada sin espacio libre
fseg zona adjunta a un segmento

Es necesario enfatizar nuevamente que free、free_frag和full_fraglos distritos en estos tres estados son independientes, por lo que lo son 直属于表空间; y fseglos distritos en el estado son 附属于某个段.

Sugerencias
Si compara el espacio de la tabla con un país, un segmento equivale a una provincia y un distrito equivale a una ciudad. Una ciudad en general pertenece a una determinada provincia, al igual que todos los distritos del estado de la fseg pertenecen a un determinado segmento. Sin embargo, los tres estados de free, free_frag y full_frag están directamente bajo el espacio de la tabla, al igual que Beijing, Tianjin y Shanghai están directamente bajo la administración estatal.

Para facilitar la gestión de estas áreas, InnoDB diseñó una estructura denominada XDES Entry (el nombre completo es Extent Descriptor Entry), cada área corresponde a una estructura XDES Entry, que registra algunos atributos del área correspondiente. Primero veamos la imagen para tener una comprensión general de esta estructura:

inserte la descripción de la imagen aquí
En la figura, podemos ver que XDES Entry es una estructura de 40 bytes, que se divide aproximadamente en 4 partes. La interpretación de cada parte es la siguiente:

  • ID de segmento (8 bytes)
    Cada segmento tiene un número único, que está representado por ID. El campo de ID de segmento aquí indica el segmento donde se encuentra el área. Por supuesto, la premisa es que el área se ha asignado a un segmento, de lo contrario, el valor de este campo no tiene sentido.

  • La parte del nodo de lista (12 bytes)
    puede conectar varias estructuras de entrada XDES en una lista enlazada. Eche un vistazo a la estructura del nodo de lista:

    inserte la descripción de la imagen aquí
    Si queremos ubicar una determinada posición en el espacio de la tabla, solo necesitamos especificar el número de página y el desplazamiento de página de la posición en el número de página especificado. entonces:

    • La combinación de Prev Node Page Number y Prev Node Offset es un puntero a la entrada XDES anterior

    • La combinación de Número de página del siguiente nodo y Desplazamiento del siguiente nodo es un puntero a la siguiente entrada XDES.

  • Estado (4 bytes)
    Este campo indica el estado de la zona. Los valores opcionales son los cuatro que mencionamos anteriormente, a saber: free, free_frag, full_frag y fseg.

  • Mapa de bits de estado de página (16 bytes)
    Esta parte ocupa un total de 16 bytes, es decir, 128 bits. Decimos que un área tiene 64 páginas por defecto, y estos 128 bits se dividen en 64 partes, y cada parte tiene 2 bits, correspondientes a una página del área. Por ejemplo, los bits 1 y 2 de la parte Mapa de bits de estado de página corresponden a la página 1 en el área, los bits 3 y 4 corresponden a la página 2 en el área, y así sucesivamente, la parte Mapa de bits de estado de página Los bits 127 y 128 bits de la correspondiente a la página 64 en la zona. El primer bit de estos dos bits indica si la página correspondiente está libre y el segundo bit aún no se usa

2.4 Lista enlazada de entradas XDES

Hasta ahora, hemos propuesto conceptos como área, segmento, área de fragmento, área adjunta a un segmento y entrada XDES. Nuestra intención original de hacer las cosas tan problemáticas es solo mejorar la eficiencia de insertar datos en la tabla sin reducir la cantidad. de datos la tabla desperdicia espacio. Ahora sabemos que insertar datos en la tabla es esencialmente insertar datos en los segmentos de nodos de hoja y en los segmentos de nodos que no son de hoja de cada índice en la tabla. También sabemos que diferentes áreas tienen diferentes estados y luego regresan al punto de partida original. y avanzar El proceso de insertar datos en un segmento:

  • Cuando haya menos datos en el segmento, primero verificará si hay free_fragun área en el espacio de la tabla con un estado de, es decir, buscará un área fragmentada con espacio libre. Si lo encuentra, luego tomará algunas páginas dispersas del e inserte los datos en él. De lo contrario, vaya al espacio de tabla para solicitar un freeárea con un estado de, es decir, un área libre, cambie el estado del área a free_frag y luego tome algunas páginas fragmentadas del nuevo área aplicada e inserte los datos en ella. Más tarde, cuando diferentes segmentos usen páginas fragmentadas, se tomarán de esta área hasta que no haya espacio libre en esta área, y luego el estado de esta área será full_frag.

    La pregunta ahora es ¿cómo sabe qué áreas en el espacio de la tabla están libres, qué áreas son free_frag y qué áreas son full_frag? Debe saber que el tamaño del espacio de la tabla se puede aumentar continuamente. Cuando crezca al nivel de GB, la cantidad de distritos será de miles. No podemos atravesar las estructuras de entrada XDES correspondientes a estos distritos cada vez, ¿verdad? En este momento, es hora de que la parte del nodo de lista en XDES Entry tenga un efecto milagroso. Podemos hacer tres cosas a través del puntero en el nodo de lista:

    Conecte la estructura de entrada XDES correspondiente al área libre a través del nodo de la lista para formar una lista enlazada. A esta lista enlazada la llamamos lista enlazada libre.

    • Conectar la estructura XDES Entry correspondiente al área cuyo estado es free_frag en una lista enlazada a través del nodo list. A esta lista enlazada la llamamos lista enlazada free_frag.

    • Conecte la estructura de entrada XDES correspondiente al área cuyo estado es full_frag en una lista enlazada a través del nodo list. A esta lista enlazada la llamamos lista enlazada full_frag.

      De esta forma, siempre que queramos encontrar un área de estado de free_frag, sacamos directamente el nodo principal de la lista enlazada de free_frag, tomamos algunas páginas dispersas de este nodo para insertar datos y lo modificamos cuando se usa el área correspondiente a este nodo. A continuación, el valor del campo de estado de este nodo se mueve de la lista enlazada free_frag a la lista enlazada full_frag. De manera similar, si no hay ningún nodo en la lista vinculada free_frag, tome directamente un nodo de la lista vinculada libre para pasar al estado de la lista vinculada free_frag, y modifique el valor del campo de estado del nodo a free_frag, y luego obtenga el fragmento del área correspondiente a este nodo La página está bien.

  • Cuando los datos del segmento hayan ocupado 32 páginas dispersas, solicite directamente un área completa para insertar los datos.

    Sigue siendo la misma pregunta, ¿cómo sabemos qué áreas pertenecen a qué segmento? Luego, ¿atravesar cada estructura de entrada XDES? Es imposible atravesar, y es imposible atravesar en esta vida, hay una lista enlazada y es un hilo de lana. Entonces, ¿agregamos todas las estructuras de entrada xdes correspondientes al área fseg a una lista vinculada? Tonto, ¿cómo pueden diferentes segmentos compartir un área? ¿Desea almacenar tanto el segmento de nodo de hoja del índice a como el segmento de nodo de hoja del índice b en una zona? Obviamente queremos que cada segmento tenga su propia lista enlazada, por lo que podemos crear una lista enlazada basada en el número de segmento (es decir, la identificación del segmento) ¿Cuántas listas enlazadas podemos construir tantos segmentos como hay? Parece ser un pequeño problema, porque puede haber muchas áreas en un segmento, algunas áreas son completamente gratuitas, algunas áreas aún tienen algunas páginas disponibles y algunas áreas no tienen páginas gratuitas para usar, por lo que debemos continuar puntos de detalle, innodb crea tres listas enlazadas para la estructura de entrada xdes correspondiente a la zona en cada segmento:

    • Lista enlazada libre: En el mismo segmento, se agregará a esta lista enlazada la estructura Entrada XDES correspondiente al área donde todas las páginas están libres. Tenga en cuenta que es diferente de la lista enlazada libre que pertenece directamente al espacio de tablas.La lista enlazada libre aquí se adjunta a un segmento determinado.
    • lista enlazada not_full: En el mismo segmento se añadirá a esta lista enlazada la estructura XDES Entry correspondiente al área que aún tiene espacio libre.
    • Lista enlazada completa: En el mismo segmento, se agregará a esta lista enlazada la estructura Entrada XDES correspondiente al área que no tiene espacio libre.

Se enfatiza nuevamente que cada índice corresponde a dos segmentos, y cada segmento mantendrá las tres listas vinculadas anteriores. Por ejemplo, tome la siguiente tabla:

create table demo9 (c1 int not null auto_increment,c2 varchar(100),c3 varchar(100),primary key (c1), key idx_c2 (c2));

Esta tabla t tiene dos índices, un índice agrupado y un índice secundario idx_c2, por lo que esta tabla tiene 4 segmentos en total, y cada segmento mantendrá las 3 listas enlazadas anteriores, un total de 12 listas enlazadas, más lo que dijimos anteriormente Hay 3 listas enlazadas que pertenecen directamente al espacio de tablas, y un total de 15 listas enlazadas deben mantenerse en todo el espacio de tablas independiente. Por lo tanto, si el segmento inserta datos cuando la cantidad de datos es relativamente grande, primero obtendrá el nodo principal de la lista enlazada not_full e insertará directamente los datos en el área correspondiente al nodo principal. se ha agotado, mueva el nodo a la lista enlazada completa.

2.4.1 Nodo base de lista enlazada

Hay muchas listas vinculadas presentadas anteriormente, ¿cómo encontrar estas listas vinculadas o cómo encontrar la posición del nodo principal o el nodo final de una lista vinculada en el espacio de la tabla? Por supuesto, InnoDB ha considerado este problema y ha diseñado una estructura llamada List Base Node, que se traduce al chino como el nodo base de la lista enlazada. Esta estructura contiene punteros al nodo principal y al nodo final de la lista enlazada e información sobre cuántos nodos están contenidos en la lista enlazada.Dibujemos un diagrama para ver el diagrama esquemático de esta estructura:

inserte la descripción de la imagen aquí
Cada lista vinculada que presentamos anteriormente corresponde a una estructura de nodo base de lista de este tipo, donde:

  • Longitud de la lista indica cuántos nodos tiene la lista vinculada.
  • Número de página del primer nodo y Desplazamiento del primer nodo indican la posición del nodo principal de la lista vinculada en el espacio de tabla.
  • Número de página del último nodo y Desplazamiento del último nodo indican la posición del nodo final de la lista vinculada en el espacio de tabla.

Generalmente, colocamos la estructura del nodo base de la lista correspondiente a una determinada lista vinculada en una posición fija en el espacio de la tabla, de modo que resulta muy sencillo localizar una determinada lista vinculada.

2.4.2 Resumen de lista enlazada

En resumen, el espacio de tabla se compone de varias áreas, y cada área corresponde a una estructura de entrada XDES.La estructura de entrada XDES correspondiente al área que pertenece directamente al espacio de tabla se puede dividir en tres listas enlazadas: free, free_frag y full_frag; Un segmento se puede adjuntar a varias áreas, y la estructura de Entrada XDES correspondiente al área en cada segmento se puede dividir en tres listas enlazadas: libre, no_lleno y lleno. Cada lista enlazada corresponde a una estructura de nodo base de lista, que registra las posiciones de los nodos de cabeza y cola de la lista enlazada y el número de nodos contenidos en la lista enlazada. Es precisamente por la existencia de estas listas enlazadas que la gestión de estas áreas se ha convertido en una cuestión muy sencilla.

2.4.3 Estructura de la sección

Como dijimos anteriormente, un segmento en realidad no corresponde a un área física continua en el tablespace, sino a un concepto lógico que consta de varias páginas dispersas y algunas áreas completas. Como cada zona tiene una entrada XDES correspondiente para registrar los atributos en esta zona, InnoDB define una estructura de entrada INODE para cada segmento para registrar los atributos en el segmento. Echemos un vistazo al diagrama esquemático:

inserte la descripción de la imagen aquí
Sus diversas partes se explican a continuación:

  • ID de segmento
    se refiere al número (ID) del segmento correspondiente a la estructura de Entrada INODE.

  • El campo NOT_FULL_N_USED
    se refiere a cuántas páginas se han utilizado en la lista enlazada NOT_FULL.

  • Los tres nodos base de lista
    definen nodos base de lista para la lista enlazada libre, la lista enlazada not_null y la lista enlazada completa del segmento respectivamente, de modo que cuando queremos encontrar el nodo principal y el nodo final de una lista enlazada de un segmento determinado, podemos ir directamente a esta parte para encontrarlos. Corresponde al nodo base de la lista de la lista vinculada.

  • El valor de Número Mágico
    se utiliza para marcar si la Entrada INODE ha sido inicializada (inicialización significa llenar los valores de cada campo). Si este número es un valor de 97937874, indica que la entrada INODE se ha inicializado, de lo contrario, no se ha inicializado. (No se preocupe por el significado especial de este valor, regulaciones).

  • El segmento Fragment Array Entry
    es una colección de algunas páginas fragmentadas y algunas áreas completas. Cada estructura Fragment Array Entry corresponde a una página fragmentada. Esta estructura tiene un total de 4 bytes, lo que indica el número de página de una página fragmentada.

Combinado con esta estructura de entrada de INODE, puede tener una comprensión más profunda de un segmento como una colección de páginas dispersas y algunas áreas completas.

2.4.4 Tipo FSP_HDR

La primera página del tablespace, número de página 0. El tipo de esta página es FSP_HDR, que almacena algunos atributos generales del espacio de tabla y la estructura de Entrada XDES correspondiente de los distritos 256 en el primer grupo.Vea el diagrama esquemático de este tipo de página directamente:

inserte la descripción de la imagen aquíUna página de tipo FSP_HDR completa se compone aproximadamente de 5 partes, y la interpretación específica de cada parte es la siguiente:

nombre nombre chino Tamaño del espacio ocupado Descripción rápida
Encabezado de archivo encabezado del archivo 38 bytes Algunos datos generales de la página
Encabezado de espacio de archivo encabezado de espacio de tabla 112 bytes Alguna información general de atributos del espacio de tabla
Entrada XDES Información de descripción del distrito 10240 bytes Almacenar la información de los atributos correspondientes a los 256 distritos de este grupo
Espacio vacio espacio no utilizado 5986 bytes Se utiliza para rellenar la estructura de la página, que no tiene ningún significado práctico.
Tráiler de archivo fin del documento 8 bytes Si la página de verificación está completa

El encabezado del archivo y el tráiler del archivo ya no se enfatizan. Entre las otras partes, el espacio vacío es un espacio sin usar. Ignorémoslo y concentrémonos en las dos partes del encabezado del espacio del archivo y la entrada XDES.

Parte de encabezado de espacio de archivos

Esta parte se utiliza para almacenar información general de atributos del espacio de tabla; consulte la siguiente figura para obtener más información:

inserte la descripción de la imagen aquí
La siguiente es una breve descripción de cada atributo:

nombre Tamaño del espacio ocupado describir
ID de espacio 4 bytes ID del espacio de tabla
No utilizado 4 bytes Estos 4 bytes no se utilizan y se pueden ignorar
Tamaño 4 bytes El número de páginas ocupadas por el tablespace actual
Límite GRATIS 4 bytes El número de página mínimo que no ha sido inicializado, y la estructura de Entrada XDES correspondiente al área mayor o igual a este número de página no ha sido agregado a la lista LIBRE
Banderas espaciales 4 bytes Algunos atributos del espacio de tablas que ocupan un espacio de almacenamiento relativamente pequeño
FRAG_N_USADO 4 bytes El número de páginas utilizadas en la lista enlazada FREE_FRAG
Lista de nodos base para lista GRATUITA 16 bytes El nodo base de la lista enlazada GRATIS
Lista de nodos base para la lista FREE_FRAG 16 bytes El nodo base de la lista enlazada FREE_FRAG
Listar nodo base para lista FULL_FRAG 16 bytes El nodo base de la lista enlazada FULL_FRAG
Siguiente ID de segmento no utilizado 8 bytes El siguiente ID de segmento no utilizado en el tablespace actual
List Base Node for SEG_INODES_FULL List 16字节 SEG_INODES_FULL链表的基节点
List Base Node for SEG_INODES_FREE List 16字节 SEG_INODES_FREE链表的基节点

这里头的Space ID、Not Used、Size这三个字段大家肯定一看就懂,其他的字段我们再详细看一下:

  • List Base Node for FREE List、List Base Node for FREE_FRAG List、List Base Node for FULL_FRAG List
    这三个大家看着太亲切了,分别是直属于表空间的FREE链表的基节点、FREE_FRAG链表的基节点、FULL_FRAG链表的基节点,这三个链表的基节点在表空间的位置是固定的,就是在表空间的第一个页面(也就是FSP_HDR类型的页面)的File Space Header部分。所以之后定位这几个链表就很简单啦。

  • FRAG_N_USED
    这个字段表明在FREE_FRAG链表中已经使用的页面数量。

  • FREE Limit
    我们知道表空间都对应着具体的磁盘文件,一开始我们创建表空间的时候对应的磁盘文件中都没有数据,所以我们需要对表空间完成一个初始化操作,包括为表空间中的区建立XDES Entry结构,为各个段建立INODE Entry结构,建立各种链表的各种操作。我们可以一开始就为表空间申请一个特别大的空间,但是实际上有绝大部分的区是空闲的,我们可以选择把所有的这些空闲区对应的XDES Entry结构加入FREE链表,也可以选择只把一部分的空闲区加入FREE链表,等啥时候空闲链表中的XDES Entry结构对应的区不够使了,再把之前没有加入FREE链表的空闲区对应的XDES Entry结构加入FREE链表,中心思想就是啥时候用到啥时候初始化,InnoDB采用的就是后者,他们为表空间定义了FREE Limit这个字段,在该字段表示的页号之前的区都被初始化了,之后的区尚未被初始化。

  • Next Unused Segment ID
    表中每个索引都对应2个段,每个段都有一个唯一的ID,那当我们为某个表新创建一个索引的时候,就意味着要创建两个新的段。那怎么为这个新创建的段找一个唯一的ID呢?去遍历现在表空间中所有的段么?我们说过,遍历是不可能遍历的,这辈子都不可能遍历,InnoDB提出了这个名叫Next Unused Segment ID的字段,该字段表明当前表空间中最大的段ID的下一个ID,这样在创建新段的时候赋予新段一个唯一的ID值就so easy啦,直接使用这个字段的值就好了。

  • Space Flags
    表空间对于一些布尔类型的属性,或者只需要寥寥几个比特位搞定的属性都放在了这个Space Flags中存储,虽然它只有4个字节,32个比特位大小,却存储了好多表空间的属性,详细情况如下表:

标志名称 占用空间(单位:bit) 描述
POST_ANTELOPE 1 表示文件格式是否大于ANTELOPE
ZIP_SSIZE 4 表示压缩页面的大小
ATOMIC_BLOBS 1 表示是否自动把值非常长的字段放到BLOB页里
PAGE_SIZE 4 页面大小
DATA_DIR 1 表示表空间是否是从默认的数据目录中获取的
SHARED 1 是否为共享表空间
TEMPORARY 1 是否为临时表空间
ENCRYPTION 1 表空间是否加密
UNUSED 18 没有使用到的比特位
  • List Base Node for SEG_INODES_FULL List和List Base Node for SEG_INODES_FREE List
    每个段对应的INODE Entry结构会集中存放到一个类型为INODE的页中,如果表空间中的段特别多,则会有多个INODE Entry结构,可能一个页放不下,这些INODE类型的页会组成两种列表:

    • SEG_INODES_FULL链表,该链表中的INODE类型的页面都已经被INODE Entry结构填充满了,没空闲空间存放额外的INODE Entry了。

    • SEG_INODES_FREE链表,该链表中的INODE类型的页面仍有空闲空间来存放INODE Entry结构。

      由于我们现在还没有详细介绍INODE类型页,所以等会说过INODE类型的页之后再回过头来看着两个链表。

XDES Entry部分

紧接着File Space Header部分的就是XDES Entry部分了,我们嘴上说过无数次,却从没见过真身的XDES Entry就是在表空间的第一个页面中保存的。我们知道一个XDES Entry结构的大小是40字节,但是一个页面的大小有限,只能存放有限个XDES Entry结构,所以我们才把256个区划分成一组,在每组的第一个页面中存放256个XDES Entry结构。大家回看那个FSP_HDR类型页面的示意图,XDES Entry 0就对应着extent 0,XDES Entry 1就对应着extent 1… 依此类推,XDES Entry255就对应着extent 255。

因为每个区对应的XDES Entry结构的地址是固定的,所以我们访问这些结构就非常简单啦。

2.4.5 XDES类型

每一个XDES Entry结构对应表空间的一个区,虽然一个XDES Entry结构只占用40字节,但你抵不住表空间的区的数量也多啊。在区的数量非常多时,一个单独的页可能就不够存放足够多的XDES Entry结构,所以我们把表空间的区分为了若干个组,每组开头的一个页面记录着本组内所有的区对应的XDES Entry结构。由于第一个组的第一个页面有些特殊,因为它也是整个表空间的第一个页面,所以除了记录本组中的所有区对应的XDES Entry结构以外,还记录着表空间的一些整体属性,这个页面的类型就是我们刚刚说完的FSP_HDR类型,整个表空间里只有一个这个类型的页面。除去第一个分组以外,之后的每个分组的第一个页面只需要记录本组内所有的区对应的XDES Entry结构即可,不需要再记录表空间的属性了,为了和FSP_HDR类型做区别,我们把之后每个分组的第一个页面的类型定义为XDES,它的结构和FSP_HDR类型是非常相似的:
inserte la descripción de la imagen aquí
与FSP_HDR类型的页面对比,除了少了File Space Header部分之外,也就是除了少了记录表空间整体属性的部分之外,其余的部分是一样一样的。

2.4.6 IBUF_BITMAP类型

每个分组的第二个页面的类型都是IBUF_BITMAP,这种类型的页里边记录了一些有关Change Buffer的信息。

2.4.7 INODE类型

再次对比前边介绍表空间的图,第一个分组的第三个页面的类型是INODE。我们前边说过InnoDB为每个索引定义了两个段,而且为某些特殊功能定义了些特殊的段。为了方便管理,他们又为每个段设计了一个INODE Entry结构,这个结构中记录了关于这个段的相关属性。而我们这会儿要介绍的这个INODE类型的页就是为了存储INODE Entry结构而存在的。

inserte la descripción de la imagen aquí
一个INODE类型的页面是由这几部分构成的:

名称 中文名 占用空间大小 简单描述
File Header 文件头部 38字节 页的一些通用信息
List Node for INODE Page List 通用链表节点 12字节 存储上一个INODE页面和下一个INODE页面的指针
INODE Entry 段描述信息 16320字节 存储段描述信息
Empty Space 尚未使用空间 6字节 用于页结构的填充,没啥实际意义
File Trailer 文件尾部 8字节 校验页是否完整

除了File Header、Empty Space、File Trailer这几个老朋友外,我们重点关注List Node for INODE Page List和INODE Entry这两个部分。

首先看INODE Entry部分,我们前边已经详细介绍过这个结构的组成了,主要包括对应的段内零散页面的地址以及附属于该段的FREE、NOT_FULL和FULL链表的基节点。每个INODE Entry结构占用192字节,一个页面里可以存储85个这样的结构。

重点看一下List Node for INODE Page List,因为一个表空间中可能存在超过85个段,所以可能一个INODE类型的页面不足以存储所有的段对应的INODE Entry结构,所以就需要额外的INODE类型的页面来存储这些结构。还是为了方便管理这些INODE类型的页面,InnoDB将这些INODE类型的页面串联成两个不同的链表:

  • SEG_INODES_FULL链表:该链表中的INODE类型的页面中已经没有空闲空间来存储额外的INODE Entry结构了。
  • SEG_INODES_FREE链表:该链表中的INODE类型的页面中还有空闲空间来存储额外的INODE Entry结构了。

想必大家已经认出这两个链表了,我们前边提到过这两个链表的基节点就存储在File Space Header里边,也就是说这两个链表的基节点的位置是固定的,所以我们可以很轻松的访问到这两个链表。以后每当我们新创建一个段(创建索引时就会创建段)时,都会创建一个INODE Entry结构与之对应,存储INODE Entry的大致过程就是这样的:

  • 先看看SEG_INODES_FREE链表是否为空,如果不为空,直接从该链表中获取一个节点,也就相当于获取到一个仍有空闲空间的INODE类型的页面,然后把该INODE Entry结构放到该页面中。当该页面中无剩余空间时,就把该页放到SEG_INODES_FULL链表中。
  • 如果SEG_INODES_FREE链表为空,则需要从表空间的FREE_FRAG链表中申请一个页面,修改该页面的类型为INODE,把该页面放到SEG_INODES_FREE链表中,与此同时把该INODE Entry结构放入该页面

2.4.8 Segment Header结构的运用

我们知道一个索引会产生两个段,分别是叶子节点段和非叶子节点段,而每个段都会对应一个INODE Entry结构,那我们怎么知道某个段对应哪个INODE Entry结构呢?所以得找个地方记下来这个对应关系。记得之前学习过的数据页MySQL之数据页结构,也就是INDEX类型的页有一个Page Header部分,所以把Page Header部分粘一下:

inserte la descripción de la imagen aquí
其中的PAGE_BTR_SEG_LEAF和PAGE_BTR_SEG_TOP都占用10个字节,它们其实对应一个叫Segment Header的结构,该结构图示如下:

inserte la descripción de la imagen aquí

各个部分的具体释义如下:

名称 占用空间大小 描述
Space ID of the INODE Entry 4字节 INODE Entry结构所在的表空间ID
Page Number of the INODE Entry 4字节 INODE Entry结构所在的页面页号
Byte Offset of the INODE Entry 2字节 INODE Entry结构在该页面中的偏移量

这样子就很清晰了,PAGE_BTR_SEG_LEAF记录着叶子节点段对应的INODE Entry结构的地址是哪个表空间的哪个页面的哪个偏移量,PAGE_BTR_SEG_TOP记录着非叶子节点段对应的INODE Entry结构的地址是哪个表空间的哪个页面的哪个偏移量。这样子索引和其对应的段的关系就建立起来了。不过需要注意的一点是,因为一个索引只对应两个段,所以只需要在索引的根页面中记录这两个结构即可。

2.5 真实表空间对应的文件大小

上边的这些概念已经压的快喘不过气了。不过独立表空间有那么大么?我到数据目录里看了,一个新建的表对应的.ibd文件只占用了96K,才6个页面大小,上边的说了那么多概念,那么大的空间占用,为什么只有96KB大小?

一开始表空间占用的空间自然是很小,因为表里边都没有数据。.ibd文件是自扩展的,随着表中数据的增多,表空间对应的文件也逐渐增大。

三、系统表空间结构

了解完了独立表空间的基本结构,系统表空间的结构也就好理解多了,系统表空间的结构和独立表空间基本类似,只不过由于整个MySQL进程只有一个系统表空间,在系统表空间中会额外记录一些有关整个系统信息的页面,所以会比独立表空间多出一些记录这些信息的页面。因为这个系统表空间最厉害,相当于是表空间之首,所以它的表空间 ID(Space ID)是0。

3.1 系统表空间整体结构

系统表空间与独立表空间的一个非常明显的不同之处就是在表空间开头有许多记录整个系统属性的页面,如图:

inserte la descripción de la imagen aquí
可以看到,系统表空间和独立表空间的前三个页面(页号分别为012,类型分别是FSP_HDRIBUF_BITMAPINODE)的类型是一致的,只是页号为3~7的页面是系统表空间特有的,我们来看一下这些多出来的页面都是干啥使的:

页号 页面类型 英文描述 描述
3 SYS Insert Buffer Header 存储Insert Buffer的头部信息
4 INDEX Insert Buffer Root 存储Insert Buffer的根页面
5 TRX_SYS Transction System 事务系统的相关信息
6 SYS First Rollback Segment 第一个回滚段的页面
7 SYS Data Dictionary Header 数据字典头部信息

除了这几个记录系统属性的页面之外,系统表空间的extent 1extent 2这两个区,也就是页号从64~191128个页面被称为Doublewrite buffer,不过上述的大部分知识都涉及到了事务和多版本控制的问题,这些问题我们会放在后边的章节中进行学习,所以现在我们只学习下有关InnoDB数据字典的知识,其余的概念在后边再看

3.2 InnoDB数据字典

我们平时使用INSERT语句向表中插入的那些记录称之为用户数据,MySQL只是作为一个软件来为我们来保管这些数据,提供方便的增删改查接口而已。但是每当我们向一个表中插入一条记录的时候,MySQL先要校验一下插入语句对应的表存不存在,插入的列和表中的列是否符合,如果语法没有问题的话,还需要知道该表的聚簇索引和所有二级索引对应的根页面是哪个表空间的哪个页面,然后把记录插入对应索引的B+树中。所以说,MySQL除了保存着我们插入的用户数据之外,还需要保存许多额外的信息,比方说:

  • 某个表属于哪个表空间,表里边有多少列
  • 表对应的每一个列的类型是什么
  • 该表有多少索引,每个索引对应哪几个字段,该索引对应的
  • 页面在哪个表空间的哪个页面
  • 该表有哪些外键,外键对应哪个表的哪些列
  • 某个表空间对应文件系统上文件路径是什么等等

上述这些数据并不是我们使用INSERT语句插入的用户数据,实际上是为了更好的管理我们这些用户数据而不得已引入的一些额外数据,这些数据也称为元数据InnoDB存储引擎特意定义了一些列的内部系统表internal system table)来记录这些这些元数据

表名 描述
SYS_TABLES 整个InnoDB存储引擎中所有的表的信息
SYS_COLUMNS 整个InnoDB存储引擎中所有的列的信息
SYS_INDEXES 整个InnoDB存储引擎中所有的索引的信息
SYS_FIELDS 整个InnoDB存储引擎中所有的索引对应的列的信息
SYS_FOREIGN 整个InnoDB存储引擎中所有的外键的信息
SYS_FOREIGN_COLS 整个InnoDB存储引擎中所有的外键对应列的信息
SYS_TABLESPACES 整个InnoDB存储引擎中所有的表空间信息
SYS_DATAFILES 整个InnoDB存储引擎中所有的表空间对应文件系统的文件路径信息
SYS_VIRTUAL 整个InnoDB存储引擎中所有的虚拟生成列的信息

这些系统表也被称为数据字典,它们都是以B+树的形式保存在系统表空间的某些页面中,其中SYS_TABLESSYS_COLUMNSSYS_INDEXESSYS_FIELDS这四个表尤其重要,称之为基本系统表basic system tables),我们先看看这4个表的结构。

3.2.1 SYS_TABLES 表

SYS_TABLES表的列

列名 描述
NAME 表的名称
ID InnoDB存储引擎中每个表都有一个唯一的ID
N_COLS 该表拥有列的个数
TYPE 表的类型,记录了一些文件格式、行格式、压缩等信息
MIX_ID 已过时,忽略
MIX_LEN 表的一些额外的属性
CLUSTER_ID 未使用,忽略
SPACE 该表所属表空间的ID

这个SYS_TABLES表有两个索引:

  • NAME列为主键的聚簇索引
  • ID列建⽴的二级索引

3.2.2 SYS_COLUMNS表

SYS_COLUMNS表的列

列名 描述
TABLE_ID 该列所属表对应的ID
POS 该列在表中是第几列
NAME 该列的名称
MTYPE main data type,主数据类型,就是那堆INT、CHAR、VARCHAR、FLOAT、DOUBLE之类的等
PRTYPE precise type,精确数据类型,就是修饰主数据类型的那堆东东,比如是否允许NULL值,是否允许负数啥的
LEN 该列最多占用存储空间的字节数
PREC 该列的精度,不过这列貌似都没有使用,默认值都是0

这个SYS_COLUMNS表只有一个聚集索引:

  • (TABLE_ID, POS)列为主键的聚簇索引

3.2.3 SYS_INDEXES表

SYS_INDEXES表的列

列名 描述
TABLE_ID 该索引所属表对应的ID
ID InnoDB存储引擎中每个索引都有一个唯一的ID
NAME 该索引的名称
N_FIELDS 该索引包含列的个数
TYPE 该索引的类型,比如聚簇索引、唯一索引、更改缓冲区的索引、全文索引、普通的二级索引等等各种类型
SPACE 该索引根页面所在的表空间ID
PAGE_NO 该索引根页面所在的页面号
MERGE_THRESHOLD 如果页面中的记录被删除到某个比例,就把该页面和相邻页面合并,这个值就是这个比例

这个SYS_INEXES表只有一个聚集索引:

  • (TABLE_ID, ID)列为主键的聚簇索引

3.2.4 SYS_FIELDS表

SYS_FIELDS表的列

列名 描述
INDEX_ID 该索引列所属的索引的ID
POS 该索引列在某个索引中是第几列
COL_NAME 该索引列的名称

这个SYS_INEXES表只有一个聚集索引:

  • (INDEX_ID, POS)列为主键的聚簇索引

3.3 Data Dictionary Header页面

只要有了上述4个基本系统表,也就意味着可以获取其他系统表以及用户定义的表的所有元数据。比方说我们想看看SYS_TABLESPACES这个系统表里存储了哪些表空间以及表空间对应的属性,那就可以:

  • SYS_TABLES表中根据表名定位到具体的记录,就可以获取到SYS_TABLESPACES表的TABLE_ID

  • 使用这个TABLE_IDSYS_COLUMNS表中就可以获取到属于该表的所有列的信息。

  • 使用这个TABLE_ID还可以到SYS_INDEXES表中获取所有的索引的信息,索引的信息中包括对应的INDEX_ID,还记录着该索引对应的B+数根页面是哪个表空间的哪个页面。

  • 使用INDEX_ID就可以到SYS_FIELDS表中获取所有索引列的信息。

也就是说这4个表是表中之表,那这4个表的元数据去哪里获取呢?没法搞了,只能把这4个表的元数据,就是它们有哪些列、哪些索引等信息硬编码到代码中,然后InnoDB拿出一个固定的页面来记录这4个表的聚簇索引和二级索引对应的B+树位置,这个页面就是页号为7的页面,类型为SYS,记录了Data Dictionary Header,也就是数据字典的头部信息。除了这4个表5个索引的根页面信息外,这个页号为7的页面还记录了整个InnoDB存储引擎的一些全局属性

inserte la descripción de la imagen aquí
可以看到这个页面由下边几个部分组成:

名称 中文名 占用空间大小 简单描述
File Header 文件头部 38字节 页的一些通用信息
Data Dictionary Header 数据字典头部信息 56字节 记录一些基本系统表的根页面位置以及InnoDB存储引擎的一些全局信息
Segment Header 段头部信息 10字节 记录本页面所在段对应的INODE Entry位置信息
Empty Space 尚未使用空间 16272字节 用于页结构的填充,没啥实际意义
File Trailer 文件尾部 8字节 校验页是否完整

可以看到这个页面里竟然有Segment Header部分,意味着InnoDB把这些有关数据字典的信息当成一个段来分配存储空间,我们就姑且称之为数据字典段吧。由于目前我们需要记录的数据字典信息非常少(可以看到Data Dictionary Header部分仅占用了56字节),所以该段只有一个碎片页,也就是页号为7的这个页。

接下来我们需要细细说一下Data Dictionary Header部分的各个字段:

  • Max Row ID:我们说过如果我们不显式的为表定义主键,而且表中也没有UNIQUE索引,那么InnoDB存储引擎会默认为我们生成一个名为row_id的列作为主键。因为它是主键,所以每条记录的row_id列的值不能重复。原则上只要一个表中的row_id列不重复就可以了,也就是说表a和表b拥有一样的row_id列也没啥关系,不过InnoDB只提供了这个Max Row ID字段,不论哪个拥有row_id列的表插入一条记录时,该记录的row_id列的值就是Max Row ID对应的值,然后再把Max Row ID对应的值加1,也就是说这个Max Row ID是全局共享的

  • Max Table ID:InnoDB存储引擎中的所有的表都对应一个唯一的ID,每次新建一个表时,就会把本字段的值作为该表的ID,然后自增本字段的值。

  • Max Index ID:InnoDB存储引擎中的所有的索引都对应一个唯一的ID,每次新建一个索引时,就会把本字段的值作为该索引的ID,然后自增本字段的值。

    Max Space ID:InnoDB存储引擎中的所有的表空间都对应一个唯一的ID,每次新建一个表空间时,就会把本字段的值作为该表空间的ID,然后自增本字段的值。

  • Mix ID Low(Unused):这个字段没啥用,跳过。

  • Root of SYS_TABLES clust index:本字段代表SYS_TABLES表聚簇索引的根页面的页号。

  • Root of SYS_TABLE_IDS sec index:本字段代表SYS_TABLES表为ID列建立的二级索引的根页面的页号。

  • Root of SYS_COLUMNS clust index:本字段代表SYS_COLUMNS表聚簇索引的根页面的页号。

  • Root of SYS_INDEXES clust index:本字段代表SYS_INDEXES表聚簇索引的根页面的页号。

  • Root of SYS_FIELDS clust index:本字段代表SYS_FIELDS表聚簇索引的根页面的页号。

  • Unused:这4个字节没用,跳过。

以上就是页号为7的页面的全部内容,看一次肯定懵,一定要反复多看几次。

3.4 information_schema系统数据库

需要注意一点的是,用户是不能直接访问InnoDB的这些内部系统表的,除非你直接去解析系统表空间对应文件系统上的文件。不过InnoDB考虑到查看这些表的内容可能有助于大家分析问题,所以在系统数据库information_schema中提供了一些以innodb开头的表:

mysql> USE information_schema;
Database changed

mysql> show tables like 'in%';
+------------------------------------+
| Tables_in_information_schema (IN%) |
+------------------------------------+
| INNODB_BUFFER_PAGE                 |
| INNODB_BUFFER_PAGE_LRU             |
| INNODB_BUFFER_POOL_STATS           |
| INNODB_CACHED_INDEXES              |
| INNODB_CMP                         |
| INNODB_CMP_PER_INDEX               |
| INNODB_CMP_PER_INDEX_RESET         |
| INNODB_CMP_RESET                   |
| INNODB_CMPMEM                      |
| INNODB_CMPMEM_RESET                |
| INNODB_COLUMNS                     |
| INNODB_DATAFILES                   |
| INNODB_FIELDS                      |
| INNODB_FOREIGN                     |
| INNODB_FOREIGN_COLS                |
| INNODB_FT_BEING_DELETED            |
| INNODB_FT_CONFIG                   |
| INNODB_FT_DEFAULT_STOPWORD         |
| INNODB_FT_DELETED                  |
| INNODB_FT_INDEX_CACHE              |
| INNODB_FT_INDEX_TABLE              |
| INNODB_INDEXES                     |
| INNODB_METRICS                     |
| INNODB_SESSION_TEMP_TABLESPACES    |
| INNODB_TABLES                      |
| INNODB_TABLESPACES                 |
| INNODB_TABLESPACES_BRIEF           |
| INNODB_TABLESTATS                  |
| INNODB_TEMP_TABLE_INFO             |
| INNODB_TRX                         |
| INNODB_VIRTUAL                     |
+------------------------------------+
31 rows in set (0.00 sec)

information_schema数据库中的这些以INNODB开头的表并不是真正的内部系统表(内部系统表就是我们上边唠叨的以SYS开头的那些表),而是在存储引擎启动时读取这些以SYS开头的系统表,然后填充到这些以INNODB_SYS开头的表中。以INNODB_SYS开头的表和以SYS开头的表中的字段并不完全一样,但供大家参考已经足矣。

四、总结

今天我们学习了关于InnoDB存储引擎表空间的结构,通篇几乎全是概念、图片,这部分知识本就枯燥乏味,但是’春天’马上就到来,最枯燥乏味的内容马上结束了。由于今天的内容都是偏理论的概念,加上篇幅原因,就不做知识点总结了。

今天的文章我第一次读原著时,一脸懵逼,好像知道了表空间结构是怎么一回事儿,但是好像又讲不出来什么,所以建议大家多看几次,我相信一句话:书读百遍,其义自见。当你一次看不懂的时候,就一定要多看几次。同时,建议大家多动手画一画结构图,这样理解起来更加深刻。

inserte la descripción de la imagen aquí

A través del estudio de este artículo, conozco la complejidad y la sutileza del diseño de bases de datos MySQL. El autor del libro original, el niño 4919, es tan profundo en la investigación de la tecnología que actualmente estoy fuera de mi alcance. Por lo tanto, sigue el ritmo del tipo grande y progresa un poco todos los días. Espero que todos eventualmente se conviertan en grandes disparado a los ojos de los demás. ¡Animémonos unos a otros!

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/130702274
Recomendado
Clasificación