Análisis en profundidad de MySQL del proceso de ejecución de un SQL

Prefacio

  • Al tratar con la base de datos todos los días, puede escribir docenas de declaraciones SQL al día, pero ¿sabe cómo interactúa el sistema con la base de datos? ¿Cómo almacena MySQL los datos y cómo gestiona las transacciones? ¿Sientes que tu mente básica está en blanco excepto por escribir algunos "seleccionar * de dual"?
  • Ahora lo llevará al mundo de MySQL, le permitirá comprender a fondo cómo interactúa el sistema con MySQL y qué hace MySQL cuando recibe la declaración SQL enviada.

Proceso de ejecución de SQL

Uno, controlador MySQL
  • Cuando el sistema se comunica con la base de datos MySQL, es imposible recibir y enviar solicitudes sin ningún motivo. Incluso si no haces nada, siempre debería haber otras "personas" haciendo algo por nosotros. Básicamente, los programadores que han utilizado MySQL La base de datos conocerá más o menos el concepto de controlador MySQL. Es este controlador MySQL el que nos ayuda a conectarnos a la base de datos en el nivel inferior. Solo después de que se establece la conexión podemos tener interacciones posteriores. Como se muestra abajo:

Inserte la descripción de la imagen aquí

  • En este caso, antes de que el sistema interactúe con MySQL, el controlador MySQL nos ayudará a establecer una conexión, y luego solo necesitamos enviar sentencias SQL para ejecutar CRUD.
  • Una solicitud SQL establecerá una conexión, múltiples solicitudes establecerán múltiples conexiones, entonces el problema está aquí, nuestro sistema definitivamente no es usado por una sola persona, en otras palabras, debe haber múltiples solicitudes para competir por la conexión al mismo tiempo.
  • Nuestro sistema web generalmente se implementa en el contenedor Tomcat, y Tomcat puede procesar múltiples solicitudes al mismo tiempo, lo que hará que múltiples solicitudes establezcan múltiples conexiones y luego las cierren después de su uso. ¿Cuál es el problema? Como se muestra abajo:

Inserte la descripción de la imagen aquí

  • El sistema java se basa en el protocolo TCP / IP cuando se conecta a la base de datos MySQL a través del controlador MySQL, por lo que si cada solicitud es para crear una nueva conexión y destruir una conexión, inevitablemente causará un desperdicio innecesario y una degradación del rendimiento, es decir, say Obviamente, no es razonable crear y destruir conexiones con frecuencia durante la solicitud de subprocesos múltiples anterior. Inevitablemente, reducirá en gran medida el rendimiento de nuestro sistema, pero si proporcionamos algunos subprocesos fijos para la conexión, ¿es innecesario crear y destruir conexiones repetidamente? Creo que los amigos conocedores sonreirán con conocimiento, sí, es el grupo de conexiones de la base de datos.
  • Grupo de conexiones de base de datos, es decir, mantener una cierta cantidad de conexiones, lo cual es conveniente para que el sistema obtenga conexiones. Puede ponerlas en el grupo cuando las use. Puede volver a colocarlas cuando las use. debe preocuparse por la creación y destrucción de conexiones, o cómo se mantiene el grupo de subprocesos.

Inserte la descripción de la imagen aquí

  • Los grupos de conexiones de bases de datos comunes incluyen Druid, C3P0 y DBCP. Los principios de implementación de los grupos de conexiones no se discutirán en profundidad aquí. El uso de grupos de conexiones ahorra en gran medida la sobrecarga de crear y destruir subprocesos. Este es el conocido "grupo" idea, ya sea un grupo de subprocesos o un grupo de conexiones HTTP, puede verlo.
En segundo lugar, el grupo de conexiones de la base de datos
  • Hasta el momento, lo que ya sabemos es que cuando nuestro sistema accede a la base de datos MySQL, la conexión establecida no se crea cada vez que se realiza una solicitud, sino que se obtiene del pool de conexiones de la base de datos, lo que resuelve el problema de la creación repetida y la pérdida de rendimiento. causado por la destrucción de la conexión es un problema. Pero aquí hay un pequeño problema: el sistema empresarial es concurrente, pero ¿hay un solo hilo en el que MySQL acepta solicitudes?
  • De hecho, este grupo también se proporciona en el sistema de arquitectura MySQL, que también es un grupo de conexiones de base de datos. Ambas partes administran cada conexión a través del grupo de conexiones de la base de datos, de modo que, por un lado, los subprocesos no necesitan competir por las conexiones antes y, lo que es más importante, no necesitan crear y destruir conexiones repetidamente.

Inserte la descripción de la imagen aquí

  • Hasta ahora, el problema de conexión entre el sistema y la base de datos MySQL se ha explicado claramente. Entonces, ¿cómo se manejan estas conexiones en la base de datos MySQL y quién las maneja?
En tercer lugar, la conexión de red debe ser manejada por hilos.
  • Los estudiantes que tienen un poco de comprensión de los conceptos básicos de computación saben que todas las conexiones en la red se manejan por hilos. La llamada conexión de red es simplemente una solicitud, y cada solicitud será procesada por un hilo correspondiente. En otras palabras, las solicitudes de declaraciones SQL son manejadas por subprocesos individuales en MySQL.

Inserte la descripción de la imagen aquí

  • ¿Cómo manejarán estos hilos estas solicitudes? ¿Qué harás?
Cuatro, interfaz SQL

Después de obtener la solicitud, el subproceso que procesa la solicitud en MySQL obtiene la declaración SQL en la interfaz SQL para su procesamiento.

Cinco, analizador de consultas

Por ejemplo, ahora hay un SQL como este:

	SELECT stuName,age,sex FROM students WHERE id=1
  • Este SQL está escrito para nuestros programadores ¿Dónde sabe la máquina de lo que estás hablando? En este momento, el analizador está en escena. Analiza las sentencias SQL pasadas por la interfaz SQL y las traduce a un lenguaje que MySQL puede reconocer En cuanto a cómo analizarlo, no necesita ser estudiado, no es más que su propio conjunto de reglas relacionadas.

Inserte la descripción de la imagen aquí

  • Después del proceso en la figura anterior, SQL ahora se ha analizado en lo que MySQL reconoce. ¿No es el siguiente paso para ser la ejecución? Es así en teoría, pero el poder de MySQL es mucho más que eso. También nos ayudará a elegir la ruta de consulta óptima (¿cuál es la ruta de consulta óptima? Es decir, MySQL ejecutará la consulta de la manera más eficiente. piensa).
  • ¿Cómo lo hizo exactamente? Se trata del optimizador de consultas de MySQL.
Seis, optimizador de consultas MySQL
  • No es necesario que nos preocupemos por la implementación específica del optimizador de consultas. Lo que debemos saber es que MySQL me ayudará a utilizar la mejor manera que él piensa para optimizar esta declaración SQL y generar un plan de ejecución. Por ejemplo, usted crea Para índices múltiples, MySQL elegirá el índice correspondiente basándose en el principio de menor costo. El costo aquí incluye principalmente dos aspectos, costo IO y costo de CPU:
    • Costo de IO: El costo de cargar datos del disco a la memoria. De forma predeterminada, el costo de IO de leer páginas de datos es 1. MySQL lee los datos en forma de páginas, es decir, cuando se utilizan ciertos datos, no solo esto Los datos se leerán y los datos adyacentes de estos datos también se leerán en la memoria. Este es el principio bien conocido de la localidad del programa, por lo que MySQL leerá una página completa cada vez, y el costo de una página es 1. Entonces, el costo de IO está relacionado principalmente con el tamaño de la página;
    • Costo de la CPU: después de leer los datos en la memoria, es necesario verificar si los datos cumplen con las condiciones y el costo de las operaciones de la CPU, como la clasificación. Obviamente, está relacionado con el número de filas. Por defecto, el costo de detectar registros es 0,2;
  • El optimizador MySQL calculará el índice con el menor costo de ejecución de "costo IO + CPU";

Inserte la descripción de la imagen aquí

  • Una vez que el optimizador realiza pasos como seleccionar el índice óptimo, llamará a la interfaz del motor de almacenamiento y comenzará a ejecutar la declaración SQL que ha sido analizada y optimizada por MySQL.
Siete, motor de almacenamiento

El optimizador de consultas llamará a la interfaz del motor de almacenamiento para ejecutar SQL, lo que significa que la ejecución real de SQL se realiza en el motor de almacenamiento. Los datos se almacenan en la memoria o en el disco (el motor de almacenamiento es un componente muy importante, que se describirá en detalle a continuación).

8. Actuador

El ejecutor es un componente muy importante, porque las operaciones de los componentes anteriores deben eventualmente ejecutarse a través del ejecutor para llamar a la interfaz del motor de almacenamiento. El ejecutor finalmente llama a la interfaz del motor de almacenamiento para completar la ejecución de SQL según una serie de planes de ejecución, de la siguiente manera:

Inserte la descripción de la imagen aquí

Motor de almacenamiento

Para ilustrar con una declaración SQL actualizada, el SQL es el siguiente:

	UPDATE students SET stuName = '小强' WHERE id = 1

Cuando el sistema emite una consulta de este tipo a MySQL, MySQL finalmente llamará al motor de almacenamiento a través del ejecutor para ejecutarlo de acuerdo con la serie de procesos descritos anteriormente. Cuando se ejecuta este SQL, los datos correspondientes a la instrucción SQL se encuentran en la memoria o en el disco. Si opera directamente en el disco, la velocidad de lectura y escritura de E / S aleatorias es definitivamente inaceptable, por lo que cada vez que SQL es ejecutado, sus datos serán cargados en la memoria Esta memoria es un componente muy importante en InnoDB: Buffer Pool.

一 、 Grupo de búfer
  • Buffer Pool (grupo de búfer) es una estructura de memoria muy importante en el motor de almacenamiento InnoDB. Como su nombre lo indica, el grupo de búfer es en realidad similar a Redis, que actúa como un caché, porque todos sabemos que los datos de MySQL se almacenan en última instancia en el disco si no existe tal Buffer Pool, entonces cada solicitud de base de datos se buscará en el disco, por lo que debe haber operaciones de IO, lo cual es definitivamente inaceptable. Pero con el Buffer Pool, almacenaremos los resultados de la consulta en el Buffer Pool por primera vez al realizar la consulta, de modo que cuando haya más solicitudes más adelante, primero consultaremos desde el buffer. Si no lo encontramos en el disco, luego colóquelo en el Buffer Pool, como se muestra a continuación:

Inserte la descripción de la imagen aquí

  • De acuerdo con la imagen de arriba, los pasos de ejecución de esta declaración SQL son más o menos así:
    • El motor de almacenamiento innodb buscará la existencia de los datos con id = 1 en el grupo de búferes;
    • Encontrado que no existe, luego irá al disco para cargarlo y almacenarlo en el grupo de búfer
    • Este registro se agregará con un candado exclusivo;
2. deshacer archivo de registro: se modifican los datos del registro
  • Deshacer, como su nombre lo indica, significa que no pasó nada, no pasó nada. Deshacer el registro son algunos registros donde no pasó nada (lo que era lo original);
  • Acabamos de decir que cuando se prepara para actualizar una declaración, la declaración se ha cargado en el grupo de búfer. De hecho, existe una operación de este tipo aquí, es decir, cuando la instrucción se carga en el grupo de búfer. Inserte un registro en el deshacer el archivo de registro, es decir, registrar el valor original del registro con id = 1. ¿Cuál es el propósito de esto?
  • La característica más importante del motor de almacenamiento Innodb es admitir transacciones. Si esta actualización falla, es decir, la transacción no se confirma, todas las operaciones de la transacción deben revertirse al estado anterior a la ejecución, es decir, cuando falla la transacción. , tampoco afectará a los datos originales, como se muestra a continuación:

Inserte la descripción de la imagen aquí

  • Aquí hay una nota extra. De hecho, MySQL también es un sistema, al igual que el sistema funcional de java que se suele desarrollar. MySQL utiliza un sistema desarrollado por su propio lenguaje correspondiente. Diseña las funciones correspondientes según sus propias necesidades. puede hacerlo ahora, luego debe ser definido por los diseñadores en primer lugar o evolucionado en función de los cambios reales de la escena. Así que todos se tranquilizan y tratan MySQL como un sistema para comprenderlo y familiarizarlo;
  • En este punto, la instrucción SQL que ejecutamos se ha cargado en el Buffer Pool, y luego comenzamos a actualizar esta declaración. La operación de actualización se ejecuta realmente en el Buffer Pool. Entonces viene el problema. Según el conjunto que solemos desarrollar Cuando los datos del grupo de búfer teórico no concuerdan con los datos de la base de datos, pensamos que los datos del caché son datos sucios . En este momento, ¿los datos del grupo de búfer se convierten en datos sucios? Así es, los datos actuales son datos sucios, y el registro en el Buffer Pool es el registro en la base de datos de Xiaoqiang es Wangcai. ¿Cómo maneja MySQL esta situación? Continúe mirando hacia abajo;
3. Rehacer archivo de registro: después de modificar los datos del registro
  • Además de cargar archivos desde el disco y guardar los registros antes de la operación en el archivo de registro de deshacer, otras operaciones se completan en la memoria La característica de los datos en la memoria es: pérdida de energía. Si el servidor donde MySQL está inactivo en este momento, entonces se perderán todos los datos del Buffer Pool. En este momento, el archivo de registro de rehacer debe mostrar su magia;
  • Rehacer registra el valor después de que se modifican los datos, y se registrará independientemente de si la transacción se envía o no. Por ejemplo, lo que se hará en este momento es actualizar el conjunto de estudiantes stuName = 'Xiaoqiang' donde id = 1; Luego esta operación se registrará en el registro de rehacer ¿Qué hay en el búfer? Cómo crear un búfer de registro de rehacer es muy simple: para mejorar la eficiencia, MySQL coloca estas operaciones en la memoria para que se completen y luego las conserva en el disco en un momento determinado.

Inserte la descripción de la imagen aquí

  • Hasta ahora, deberíamos estar familiarizados con cómo el ejecutor de MySQL llama al motor de almacenamiento para cargar una parte de SQL en el grupo de búfer y qué registros se deben registrar. El proceso es el siguiente:
    • Prepárese para actualizar una declaración SQL;
    • MySQL (innodb) primero irá al grupo de búfer (BufferPool) para encontrar los datos, si no los encuentra, irá al disco para encontrarlos, y si los encuentra, cargará los datos en el grupo de búfer (BufferPool );
    • Mientras se carga en el Buffer Pool, el registro original de estos datos se guardará en el archivo de registro de deshacer;
    • Innodb realizará operaciones de actualización en el Buffer Pool;
    • Los datos actualizados se registrarán en el búfer de registro de rehacer;
  • Los pasos mencionados anteriormente están todos operando en condiciones normales, pero el diseño y optimización del programa no solo se realiza para estas condiciones normales, sino también para las áreas críticas y condiciones extremas para optimizar el diseño;
  • Si el servidor no funciona en este momento, los datos de la caché aún se pierden. Es realmente molesto, incluso si los datos siempre se pierden, ¿se pueden guardar directamente en el disco en lugar de en la memoria? Obviamente no, porque se ha introducido anteriormente que el propósito de las operaciones en la memoria es mejorar la eficiencia.
  • En este punto, si MySQL realmente falla, no importa, porque MySQL considerará que esta transacción es un error, por lo que los datos siguen siendo los mismos que antes de la actualización y no habrá impacto.
  • Ok, el estado de cuenta también se actualiza, luego se debe enviar el valor actualizado, es decir, se debe enviar la transacción, porque siempre que la transacción se envíe correctamente, el último cambio se guardará en la base de datos y se aún debe presentarse antes de la transacción Otras operaciones relacionadas;
  • Para conservar los datos en el búfer de registro de rehacer en el disco es escribir los datos en el búfer de registro de rehacer en el archivo del disco de registro de rehacer. En general, la estrategia para escribir los datos del búfer de registro de rehacer en el disco es vaciar inmediatamente los datos al disco (específicamente La estrategia se describirá en detalle en el siguiente resumen), como se muestra en la figura:

Inserte la descripción de la imagen aquí

  • Si el servidor de la base de datos deja de funcionar después de que el búfer de registro de rehacer se descargue en el disco, ¿qué debemos hacer con los datos actualizados? En este momento, los datos están en la memoria, ¿no se pierden los datos? No, los datos no se perderán esta vez, porque los datos en el búfer del registro de rehacer se han escrito en el disco y se han conservado. Incluso si la base de datos está inactiva, MySQL rehacerá el archivo de registro la próxima vez que se reinicie. el contenido se restaura en el Buffer Pool (Tengo entendido que el mecanismo de persistencia de Redis es similar. Cuando se inicia Redis, comprobará RDB o AOF o ambos, y restaurará los datos de acuerdo con el archivo persistente. En la memoria);
  • Hasta ahora, ¿qué ha hecho para llamar a la interfaz del motor de almacenamiento desde el ejecutor?
    • Prepárese para actualizar una declaración SQL;
    • MySQL (innodb) primero irá al grupo de búferes (BufferPool) para encontrar este dato, irá al disco si no lo encuentra, y si lo encuentra, cargará este dato;
    • Al grupo de búfer (BufferPool) 3. Mientras se carga en el grupo de búfer, el registro original de estos datos se guardará en el archivo de registro de deshacer;
    • Innodb realizará operaciones de actualización en el Buffer Pool;
    • Los datos actualizados se registrarán en el búfer de registro de rehacer;
    • El tiempo de MySQL para confirmar la transacción, los datos de escritura rehacerán el búfer de registro en el archivo de registro de rehacer en el disco se puede configurar a través del pincel innodb_flush_log_at_trx_commit parámetros:
      Un valor de 0 indica que no hay pincel en el disco; el
      valor de 1 indica que el disco se pince inmediatamente ; el
      valor 2 significa flash a la caché del sistema operativo primero;
    • Cuando myslq se reinicia, el registro de rehacer se restaurará en el grupo de búferes;
Cuatro, archivo de registro de bin: registre todo el proceso de operación
  • El registro de rehacer presentado anteriormente es un archivo de registro exclusivo del motor de almacenamiento InnoDB, y el registro bin es un registro de nivel MySQL. Las cosas registradas en el registro de rehacer están sesgadas hacia propiedades físicas, como: "qué datos y qué cambios se han realizado". Bin log está sesgado hacia la naturaleza lógica, similar a: "actualizado el registro con id 1 en la tabla de estudiantes" Las características principales de los dos se resumen a continuación:
    • Nature redo Logbin Log Tamaño del archivo El tamaño del redo log es fijo (también se puede establecer en la configuración, generalmente el valor predeterminado es suficiente) bin log se puede configurar mediante el parámetro de configuración max_bin log_size para establecer el tamaño de cada archivo de registro bin ( pero generalmente no se recomienda modificar).
    • El registro de rehacer lo implementa la capa del motor InnoDB (es decir, es exclusivo del almacenamiento de Innodb). El registro de bin se implementa mediante la capa de MySQL. Todos los motores pueden utilizar el método de registro de registro de bin. El registro de rehacer utiliza escritura circular para registrar. Al escribir en Al final, volverá al principio para escribir registros de forma circular.
    • El registro del contenedor se registra agregando. Cuando el tamaño del archivo es mayor que el valor dado, el registro posterior se registrará en el nuevo archivo. Usar el registro de rehacer del escenario es adecuado para la protección contra fallas (en realidad, es muy similar a la persistencia de Redis) Características) bin log es adecuado para la replicación maestro-esclavo y la recuperación de datos;
    • ¿Cómo se descarga el archivo de registro bin en el disco? La limpieza del registro bin tiene una estrategia relacionada. La estrategia se puede modificar mediante sync_bin log. El valor predeterminado es 0, lo que significa que se escribe primero en la caché del sistema operativo, lo que significa que cuando el la transacción está confirmada, los datos no irán directamente al disco, por lo que si los datos del registro de la bandeja están inactivos, aún se perderán. Por lo tanto, se recomienda establecer sync_bin log en 1, lo que significa escribir datos directamente en el archivo de disco.
  • Hay varios modos de parpadeo del registro del contenedor:
    • DECLARACIÓN: Replicación basada en sentencias SQL (replicación basada en sentencias, SBR), cada sentencia SQL que modificará los datos se registrará en el registro bin:
      [Ventajas]: No es necesario registrar los cambios de cada línea, lo que reduce el cantidad de registro de bin. Guarde IO, mejorando así el rendimiento
      [Desventajas]: En algunos casos, provocará datos maestro-esclavo inconsistentes, como ejecutar sysdate (), slepp (), etc.
    • FILA: Replicación basada en filas (RBR), no registra la información de contexto de cada declaración SQL, solo necesita registrar qué datos se modifican:
      [Ventajas]: No habrá procedimientos almacenados bajo ciertas circunstancias, O el problema de que la función o la llamada del disparador y el disparador no se pueden copiar correctamente;
      [Desventaja]: Se generará una gran cantidad de registros, especialmente cuando se usa la tabla de alteración, los registros se dispararán;
  • MIXTO: replicación basada en mixto (MBR) basada en los modos STATMENT y ROW. La replicación general usa el modo STATEMENT para guardar el registro de bin. Para operaciones que no se pueden replicar en el modo STATEMENT, use el modo ROW para guardar el registro de bin. Dado que bin log también es un archivo de registro, ¿qué es lo que registra datos? De hecho, cuando MySQL confirma una transacción, no solo escribe los datos en el búfer del registro de rehacer en el archivo de registro de rehacer, sino que también registra los datos modificados en el archivo de registro bin, y esta vez también registra el bin modificado. el nombre del archivo de registro y el contenido modificado en el registro bin se registran en el registro de rehacer y, finalmente, la marca de confirmación se escribe al final del registro de rehacer, lo que significa que la transacción se comprometió con éxito.

Inserte la descripción de la imagen aquí

  • Si los datos se escriben en el archivo de registro bin y la base de datos está inactiva justo después de que se completa la escritura, ¿se perderán los datos?
  • Lo primero que hay que asegurarse es que mientras no haya una marca de confirmación al final del registro de rehacer, esto indica que la transacción debe haber fallado. Pero los datos no se pierden, porque se han registrado en el archivo de disco de registro de rehacer. Cuando MySQL se reinicia, los datos del registro de rehacer se restaurarán (cargarán) en el Buffer Pool.
  • Bueno, hasta ahora, básicamente hemos introducido una operación de actualización básicamente, pero ¿sientes que falta algo que no se ha hecho? ¿También encontró que el registro actualizado en este momento solo se ejecuta en la memoria, incluso si la máquina está inactiva y reanudada, solo está cargando el registro actualizado en el Buffer Pool? En este momento, el registro en la base de datos MySQL todavía es El valor antiguo, es decir, los datos en la memoria siguen siendo datos sucios en nuestra opinión, ¿qué debemos hacer en este momento?
  • De hecho, MySQL tendrá un subproceso en segundo plano, que descargará los datos sucios en nuestro Buffer Pool a la base de datos MySQL en un momento determinado, para que la memoria y los datos de la base de datos estén unificados.

Inserte la descripción de la imagen aquí

Resumen de este artículo

  • Acerca de los conceptos de Buffer Pool, Redo Log Buffer, Undo Log, Reha Log y Bin Log:
    • Buffer Pool es un componente muy importante de MySQL, porque las operaciones de adición, eliminación y modificación de la base de datos se realizan en el Buffer Pool;
    • El registro de deshacer registra el aspecto antes de la operación de datos;
    • El registro de rehacer registra la apariencia de los datos después de ser manipulados (el registro de rehacer es exclusivo del motor de almacenamiento Innodb);
    • El registro del contenedor registra todo el registro de la operación (esto es muy importante para la replicación maestro-esclavo);
  • Descripción del proceso desde la preparación para actualizar un dato hasta la confirmación de la transacción:
    • Primero, el ejecutor consulta los datos de acuerdo con el plan de ejecución de MySQL, primero consulta los datos del grupo de búfer, si no, consulta la base de datos, y si se encuentra la consulta, la coloca en el grupo de búfer;
    • Cuando los datos se almacenan en caché en el grupo de búferes, se escribirán en el archivo de registro de deshacer;
    • La acción de actualización se completa en BufferPool y los datos actualizados se agregarán al búfer de registro de rehacer al mismo tiempo
    • Una vez completada, puede enviar la transacción y se realizarán las siguientes tres cosas durante el envío;
    • (Lo primero) Vacíe los datos en el búfer de registro de rehacer al archivo de registro de rehacer;
    • (Lo segundo) Escriba este registro de operación en el archivo de registro bin;
    • (La tercera cosa) Registre el nombre del archivo de registro bin y la ubicación del contenido actualizado en el registro bin en el registro de rehacer, y agregue una marca de confirmación al final del registro de rehacer.

Supongo que te gusta

Origin blog.csdn.net/Forever_wj/article/details/113098280
Recomendado
Clasificación