Recomendaciones para características de MySQL en Aurora MySQL - Amazon Aurora

Recomendaciones para características de MySQL en Aurora MySQL

A continuación se describen las funciones que están disponibles en Aurora MySQL para ofrecer compatibilidad con MySQL. Sin embargo, tienen problemas de rendimiento, escalabilidad, estabilidad o compatibilidad en el entorno de Aurora. Por lo tanto, le recomendamos que siga determinadas directrices en el uso de estas características. Por ejemplo, le recomendamos que no utilice determinadas funciones para las implementaciones de Aurora de producción.

Uso de la replicación de varios subprocesos en Aurora MySQL

Con la replicación de registros binarios de múltiples procesos, un subproceso SQL lee los eventos del registro de retransmisión y los pone en cola para que se apliquen los subprocesos de trabajo de SQL. Los subprocesos de trabajo SQL se administran mediante un subproceso coordinador. Los eventos de registros binarios se aplican en paralelo cuando es posible.

La replicación de varios subprocesos se admite en la versión 3 de Aurora MySQL y la versión 2.12.1 de Aurora MySQL y versiones posteriores.

Para versiones de Aurora MySQL anteriores a 3.04, Aurora utiliza de forma predeterminada la replicación de subproceso único cuando se utiliza un clúster de base de datos de Aurora MySQL como réplica de lectura para la replicación de registros binarios.

Las versiones anteriores a la versión 2 de Aurora MySQL heredó de MySQL Community Edition varios problemas relativos a la replicación con varios subprocesos. Para esas versiones, no es recomendable usar la replicación con varios subprocesos en entornos de producción.

Si utiliza la replicación de varios subprocesos, le recomendamos que realice pruebas exhaustivas.

Para obtener más información acerca del uso de la replicación en Amazon Aurora, consulte Replicación con Amazon Aurora. Para obtener más información sobre la replicación de varios subprocesos en Aurora MySQL, consulte Replicación de registros binarios de varios subprocesos.

Invocación de funciones de AWS Lambda mediante funciones de MySQL nativas

Recomendamos utilizar las funciones nativas de MySQL lambda_sync y lambda_async para invocar las funciones de Lambda.

Si utiliza el procedimiento obsoleto mysql.lambda_async, es recomendable integrar las llamadas al procedimiento mysql.lambda_async en un procedimiento almacenado. Puede llamar a este procedimiento almacenado desde distintos orígenes, como los disparadores o el código cliente. Este método puede ayudar a evitar los problemas de discrepancia de la impedancia y facilitar a los programadores de bases de datos la invocación de las funciones de Lambda.

Para obtener más información acerca de la invocación de funciones de Lambda desde Amazon Aurora, consulte Invocación de una función de Lambda desde un clúster de base de datos de Amazon Aurora MySQL.

Evitar las transacciones de XA con Amazon Aurora MySQL

No es recomendable usar transacciones de eXtended Architecture (XA) con Aurora MySQL, ya que pueden provocar tiempos de recuperación prolongados si la transacción de XA se encuentra en el estado PREPARED. Si debe usar transacciones de XA con Aurora MySQL, siga estas prácticas recomendadas:

  • No deje ninguna transacción de XA abierta en el estado PREPARED.

  • Mantenga las transacciones de XA tan pequeñas como sea posible.

Para obtener más información acerca del uso de transacciones de XA con MySQL, consulte XA Transactions en la documentación de MySQL.

Mantenimiento de las claves externas activadas durante las instrucciones DML

Le recomendamos encarecidamente que no ejecute instrucciones en lenguaje de definición de datos (DDL) cuando la variable foreign_key_checks está definida en 0 (apagada).

Si tiene que insertar o actualizar filas que requieran una infracción transitoria de claves externas, siga estos pasos:

  1. Establezca foreign_key_checks en 0.

  2. Realice sus cambios de lenguaje de manipulación de datos (DML).

  3. Asegúrese de que los cambios completados no infrinjan ninguna restricción de claves externas.

  4. Establezca foreign_key_checks en 1 (activado).

Además, siga estas otras prácticas recomendadas para restricciones de clave externa:

  • Asegúrese de que sus aplicaciones cliente no establezcan la variable foreign_key_checks en 0 como parte de la variable init_connect.

  • Si una restauración a partir de una copia de seguridad lógica mysqldump deja de funcionar o está incompleta, asegúrese de que foreign_key_checks esté definido en 1 antes de iniciar alguna otra operación en la misma sesión. Una copia de seguridad lógica establece foreign_key_checks en 0 cuando se inicia.

Configuración de la frecuencia de vaciado del búfer de registro

En MySQL Community Edition, para que las transacciones sean duraderas, el búfer de registro de InnoDB debe vaciarse en un almacenamiento duradero. Utilice el parámetro innodb_flush_log_at_trx_commit para configurar la frecuencia con la que se vacía el búfer de registro en un disco.

Al establecer el parámetro innodb_flush_log_at_trx_commit en el valor predeterminado de 1, el búfer de registro se vacía en cada confirmación de transacción. Esta configuración ayuda a mantener la base de datos compatible con ACID. Le recomendamos que utilice el ajuste predeterminado de 1.

Cambiar innodb_flush_log_at_trx_commit a un valor no predeterminado puede ayudar a reducir la latencia del lenguaje de manipulación de datos (DML), pero se sacrifica la durabilidad de los registros. Esta falta de durabilidad hace que la base de datos ACID no sea compatible. Recomendamos que sus bases de datos cumplan con ACID para evitar el riesgo de pérdida de datos si se reinicia el servidor. Para obtener más información sobre este parámetro, consulte innodb_flush_log_at_trx_commit.

En Aurora MySQL, el procesamiento de un registro de rehacer se descarga a la capa de almacenamiento, por lo que no se descargan los archivos de registro en la instancia de base de datos. Cuando se emite una escritura, los registros de rehacer se envían desde la instancia de base de datos del escritor directamente al volumen del clúster de Aurora. Las únicas escrituras que cruzan la red son los registros de rehacer. Nunca se escribe ninguna página desde el nivel de base de datos.

De manera predeterminada, cada subproceso que confirma una transacción espera la confirmación del volumen del clúster de Aurora. Esta confirmación indica que este registro y todos los registros anteriores de rehacer están escritos y han alcanzado el quórum. Si se conservan los registros y se alcanza el quórum, la transacción es duradera, ya sea mediante confirmación automática o explícita. Para obtener más información sobre la arquitectura de almacenamiento de Aurora, consulte Amazon Aurora storage demystified.

Aurora MySQL no vacía los registros en los archivos de datos como lo hace MySQL Community Edition. Sin embargo, puede usar el parámetro innodb_flush_log_at_trx_commit para relajar las restricciones de durabilidad al escribir registros de rehacer en el volumen del clúster de Aurora.

Para Aurora MySQL, versión 2.

  • innodb_flush_log_at_trx_commit = 0 o 2: la base de datos no espera a que se confirme que los registros redo se han escrito en el volumen del clúster de Aurora.

  • innodb_flush_log_at_trx_commit = 1: la base de datos espera a que se confirme que los registros redo se han escrito en el volumen del clúster de Aurora.

Para Aurora MySQL, versión 3:

  • innodb_flush_log_at_trx_commit = 0: la base de datos no espera a que se confirme que los registros redo se han escrito en el volumen del clúster de Aurora.

  • innodb_flush_log_at_trx_commit = 1 o 2: la base de datos espera a que se confirme que los registros redo se han escrito en el volumen del clúster de Aurora.

Por lo tanto, para obtener el mismo comportamiento no predeterminado en Aurora MySQL versión 3 que con el valor establecido en 0 o 2 de Aurora MySQL versión 2, establezca el parámetro en 0.

Si bien estas configuraciones pueden reducir la latencia de DML para el cliente, también pueden provocar la pérdida de datos en caso de una conmutación por error o un reinicio. Por lo tanto, le recomendamos que mantenga el parámetro innodb_flush_log_at_trx_commit establecido en el valor predeterminado de 1.

Si bien la pérdida de datos puede ocurrir tanto en MySQL Community Edition como en Aurora MySQL, el comportamiento difiere en cada base de datos debido a sus diferentes arquitecturas. Estas diferencias arquitectónicas pueden provocar diversos grados de pérdida de datos. Para asegurarse de que su base de datos es compatible con ACID, establezca siempre innodb_flush_log_at_trx_commit en 1.

nota

En la versión 3 de Aurora MySQL, antes de poder cambiar innodb_flush_log_at_trx_commit a un valor distinto de 1, primero debe cambiar el valor de innodb_trx_commit_allow_data_loss a 1. Al hacerlo, acepta el riesgo de una posible pérdida de datos.

Minimización y solución de problemas de los interbloqueos de Aurora MySQL

Los usuarios que ejecutan cargas de trabajo que sufren regularmente infracciones de las restricciones en índices secundarios únicos o claves externas, al modificar registros de la misma página de datos de forma simultánea, podrían experimentar un aumento de los interbloqueos y los tiempos de espera de bloqueo. Estos interbloqueos y tiempos de espera se deben a una corrección de errores de MySQL Community Edition.

Esta corrección se incluye en las versiones 5.7.26 y posteriores de MySQL Community Edition, y se ha introducido también en las versiones 2.10.3 y posteriores de Aurora MySQL. La corrección es necesaria para aplicar la serialización mediante la implementación de un bloqueo adicional para este tipo de operaciones del lenguaje de manipulación de datos (DML) en los cambios realizados en los registros de una tabla de InnoDB. Este problema se descubrió como parte de una investigación sobre los problemas de interbloqueos introducidos en una corrección de errores anterior de MySQL Community Edition.

La corrección cambió el manejo interno de la reversión parcial de una actualización de tuplas (filas) en el motor de almacenamiento de InnoDB. Las operaciones que generan infracciones de restricciones en claves externas o índices secundarios únicos provocan una reversión parcial. Esto incluye, entre otras, instrucciones INSERT...ON DUPLICATE KEY UPDATE, REPLACE INTO, y INSERT IGNORE simultáneas (upserts).

En este contexto, la reversión parcial no se refiere a la reversión de las transacciones a nivel de la aplicación, sino a la reversión interna de InnoDB de los cambios en un índice en clúster cuando se detecta una infracción de una restricción. Supongamos que se encuentra un valor de clave duplicado durante una operación upsert.

En una operación de inserción normal, InnoDB crea de forma atómica entradas de índice secundario y en clúster para cada índice. Si InnoDB detecta un valor duplicado en un índice secundario único durante una operación upsert, la entrada insertada en el índice en clúster debe revertirse (reversión parcial) y, a continuación, debe aplicarse la actualización a la fila duplicada existente. Durante este paso de reversión parcial interna, InnoDB debe bloquear cada registro que se detecte como parte de la operación. La solución garantiza la serialización de las transacciones al introducir un bloqueo adicional después de la reversión parcial.

Minimización de interbloqueos de InnoDB

Puede adoptar los siguientes métodos para reducir la frecuencia de los interbloqueos en la instancia de base de datos. Encontrará más ejemplos en la documentación de MySQL.

  1. Para reducir las probabilidades de que se produzcan interbloqueos, confirme las transacciones inmediatamente después de realizar un conjunto de cambios relacionados. Para ello, puede dividir las transacciones de gran tamaño (actualizaciones de varias filas entre confirmaciones) en transacciones más pequeñas. Si va a insertar filas por lotes, intente reducir el tamaño de las inserciones por lotes, especialmente cuando utilice las operaciones upsert mencionadas anteriormente.

    Para reducir el número de posibles reversiones parciales, puede probar algunos de los siguientes métodos:

    1. Sustituya las operaciones de inserción por lotes por inserciones de filas de una en una. Esto puede reducir el tiempo durante el que las transacciones mantienen bloqueos que pueden generar conflictos.

    2. En lugar de usar REPLACE INTO, reescriba la instrucción SQL como una transacción de múltiples instrucciones, como la siguiente:

      BEGIN; DELETE conflicting rows; INSERT new rows; COMMIT;
    3. En lugar de usar INSERT...ON DUPLICATE KEY UPDATE, reescriba la instrucción SQL como una transacción de múltiples instrucciones, como la siguiente:

      BEGIN; SELECT rows that conflict on secondary indexes; UPDATE conflicting rows; INSERT new rows; COMMIT;
  2. Evite las transacciones de larga duración, activas o inactivas, que podrían mantener bloqueos. Esto incluye sesiones interactivas de clientes MySQL que podrían estar abiertas durante un periodo de tiempo prolongado con una transacción no confirmada. Al optimizar los tamaños de las transacciones o los tamaños de lotes, el resultado puede variar en función de varios factores, como la simultaneidad, el número de duplicados y la estructura de la tabla. Cualquier cambio debe implementarse y probarse en función de su carga de trabajo.

  3. En algunas situaciones, pueden producirse interbloqueos cuando dos transacciones intentan acceder a los mismos conjuntos de datos, ya sea en una o varias tablas, en órdenes diferentes. Para evitarlo, puede modificar las transacciones para que accedan a los datos en el mismo orden, serializando así el acceso. Por ejemplo, cree una cola de transacciones que deben completarse. Este método puede ayudar a evitar interbloqueos cuando se realizan varias transacciones al mismo tiempo.

  4. Añadir índices cuidadosamente seleccionados a las tablas puede mejorar la selectividad y reducir la necesidad de acceder a las filas, lo que disminuye los bloqueos.

  5. Si se encuentra con un bloqueo de espacio, puede modificar el nivel de aislamiento de las transacciones por READ COMMITTED para la sesión o la transacción para evitarlo. Para obtener más información sobre los niveles de aislamiento de InnoDB y sus comportamientos, consulte Transaction isolation levels (Niveles de aislamiento de las transacciones) en la documentación de MySQL.

nota

Aunque puede tomar medidas para reducir la posibilidad de que se produzcan interbloqueos, son un comportamiento normal de la base de datos y pueden producirse a pesar de todo. Las aplicaciones deben tener la lógica necesaria para gestionar los interbloqueos cuando se encuentren. Por ejemplo, implemente lógica de reintento e interrupción en la aplicación. Es mejor solucionar la causa principal del problema, pero si se produce un interbloqueo, la aplicación tiene la opción de esperar y volver a intentarlo.

Supervisión de interbloqueos de InnoDB

Pueden producirse interbloqueos en MySQL cuando las transacciones de la aplicación intentan aceptar bloqueos a nivel de tabla y fila de una forma que da lugar a una espera circular. Un interbloqueo ocasional de InnoDB no tiene por qué ser necesariamente un problema, ya que el motor de almacenamiento de InnoDB detecta la condición inmediatamente y anula una de las transacciones automáticamente. Si se encuentra con interbloqueos con frecuencia, le recomendamos que revise y modifique la aplicación para reducir los problemas de rendimiento y evitar los interbloqueos. Cuando la detección de interbloqueos está activada (opción predeterminada), InnoDB detecta automáticamente los interbloqueos de transacciones y revierte una transacción o transacciones para salir del interbloqueo. InnoDB intenta seleccionar transacciones pequeñas para revertirlas, donde el tamaño de una transacción viene determinado por el número de filas insertadas, actualizadas o eliminadas.

  • Instrucción SHOW ENGINE: la instrucción SHOW ENGINE INNODB STATUS \G contiene detalles del último interloqueo encontrado en la base de datos desde el último reinicio.

  • Registro de errores de MySQL: si se encuentra interbloqueos frecuentes en los que la salida de la instrucción SHOW ENGINE no es adecuada, puede activar el parámetro del clúster de base de datos innodb_print_all_deadlocks.

    Cuando este parámetro está activado, la información sobre todos los interbloqueos en las transacciones de los usuarios de InnoDB se registra en el registro de errores de Aurora MySQL.

  • Métricas de Amazon CloudWatch: también le recomendamos que supervise de forma proactiva los interbloqueos mediante la métrica de CloudWatch Deadlocks. Para obtener más información, consulte Métricas de nivel de instancia para Amazon Aurora.

  • Registros de Amazon CloudWatch: con Registros de CloudWatch, puede ver métricas, analizar datos de registro y crear alarmas en tiempo real. Para obtener más información, consulte Monitor errors in Amazon Aurora MySQL and Amazon RDS for MySQL using Amazon CloudWatch and send notifications using Amazon SNS (Supervisión de errores en Amazon Aurora MySQL y Amazon RDS para MySQL mediante Amazon CloudWatch y envío de notificaciones mediante Amazon SNS).

    Si utiliza Registros de CloudWatch con la opción innodb_print_all_deadlocks activada, puede configurar alarmas para que le notifiquen cuando el número de interbloqueos supere un umbral determinado. Para definir un umbral, le recomendamos que observe las tendencias y utilice un valor basado en su carga de trabajo normal.

  • Información sobre rendimiento: al utilizar Información sobre rendimiento, puede supervisar las métricas innodb_deadlocks y innodb_lock_wait_timeout. Para obtener más información sobre estas métricas, consulte Contadores no nativos para Aurora MySQL.