Todos los productos
Search
Centro de documentos

PolarDB:Sentencias DDL no bloqueantes

Última actualización: Sep 05, 2026

ALTER TABLE en una tabla grande puede bloquear todas las transacciones nuevas durante minutos u horas. Cuando una sentencia DDL bloqueante mantiene abierta la cola de solicitudes del bloqueo MDL-X, cada transacción que accede a esa tabla se acumula detrás de ella. Si la cola crece demasiado, el agotamiento de conexiones puede dejar inoperativa toda la aplicación. Las sentencias DDL no bloqueantes eliminan este riesgo: reintentan obtener el bloqueo en intervalos cortos y liberan su posición en la cola entre intentos para que las transacciones nuevas sigan ejecutándose.

Cómo funciona

El sistema de bloqueo de metadatos (MDL) de MySQL protege las tablas durante los cambios de esquema. Una sentencia DDL bloqueante solicita un bloqueo exclusivo MDL-X y mantiene bloqueada la cola de solicitudes hasta que lo obtiene. Como MDL-X tiene la prioridad más alta, cada transacción nueva que accede a la tabla se acumula detrás de la sentencia DDL, incluso si esta aún espera que termine una transacción anterior.

Las sentencias DDL no bloqueantes cambian este comportamiento:

  1. La sentencia DDL intenta obtener el bloqueo MDL-X dentro de un tiempo de espera corto (loose_polar_nonblock_ddl_lock_wait_timeout, valor predeterminado: 1 segundo).

  2. Si el bloqueo no está disponible, la sentencia DDL libera por completo su posición en la cola. Al desbloquearse la cola, las transacciones pendientes y entrantes pueden obtener sus propios bloqueos y continuar con normalidad.

  3. Después de un intervalo configurable (loose_polar_nonblock_ddl_retry_interval, valor predeterminado: 6 segundos), la sentencia DDL reintenta la operación.

  4. Los pasos 2 y 3 se repiten hasta loose_polar_nonblock_ddl_retry_times intentos.

Durante los intervalos de reintento, la tabla permanece totalmente accesible. Las transacciones por segundo (TPS) pueden disminuir brevemente cuando la sentencia DDL obtiene el bloqueo, pero nunca llegan a cero.

Nota

Las sentencias DDL no bloqueantes tienen menor prioridad que las bloqueantes y una mayor probabilidad de no obtener el bloqueo MDL-X. Utilícelas cuando la continuidad del negocio sea más importante que la velocidad del cambio de esquema.

Versiones compatibles

Las sentencias DDL no bloqueantes requieren una de a continuación versiones:

  • PolarDB for MySQL 8.0.1 en la versión de revisión 8.0.1.1.29 o posterior

  • PolarDB for MySQL 8.0.2 en la versión de revisión 8.0.2.2.12 o posterior

Para comprobar la versión de revisión de su clúster, consulte Engine versions 5.6, 5.7, and 8.0.

Sentencias DDL compatibles

Las sentencias que admiten sentencias DDL no bloqueantes dependen de su versión de revisión.

Versión de revisión

Sentencias compatibles

Notas

8.0.1.1.29 o posterior, o 8.0.2.2.12

Solo ALTER TABLE

Para desfragmentar una tabla InnoDB, utilice ALTER TABLE table_name ENGINE=InnoDB en lugar de OPTIMIZE TABLE table_name

8.0.2.2.13 o posterior

ALTER TABLE, OPTIMIZE TABLE, TRUNCATE TABLE

—

Habilitar las sentencias DDL no bloqueantes

Los cuatro parámetros son de nivel de sesión. Establézcalos en la misma sesión antes de ejecutar la sentencia DDL.

Paso 1: Habilite el modo DDL no bloqueante

SET SESSION loose_polar_nonblock_ddl_mode = ON;

El valor predeterminado de loose_polar_nonblock_ddl_mode es OFF.

Paso 2: Configure el comportamiento de reintento

SET SESSION loose_polar_nonblock_ddl_retry_times = 4194304;
SET SESSION loose_polar_nonblock_ddl_retry_interval = 6;
SET SESSION loose_polar_nonblock_ddl_lock_wait_timeout = 1;

Parámetro

Valor predeterminado

Valores válidos

Unidad

Cuándo modificarlo

loose_polar_nonblock_ddl_retry_times

0 (derivado de lock_wait_timeout)

0–31536000

—

Establezca 4194304 para cambios de esquema prolongados en tablas grandes

loose_polar_nonblock_ddl_retry_interval

6

1–31536000

Segundos

Auméntelo para reducir la contención de bloqueos; redúzcalo para terminar la sentencia DDL más rápido

loose_polar_nonblock_ddl_lock_wait_timeout

1

1–31536000

Segundos

Auméntelo si el bloqueo no se obtiene con suficiente frecuencia bajo una carga de escritura intensa

Para obtener más información sobre cómo aplicar estos parámetros, consulte Configure cluster and node parameters.

Paso 3: Ejecute la sentencia DDL

ALTER TABLE table_name ADD INDEX index_name (column1, column2, column3);

La sentencia se ejecuta con comportamiento no bloqueante en la sesión actual. Las demás sesiones no se ven afectadas.

Prueba de rendimiento

A continuación se comparan las sentencias DDL bloqueantes, las no bloqueantes y la herramienta de cambio de esquema en línea gh-ost mediante SysBench. Para obtener más información sobre SysBench, consulte OLTP performance test.

Test environment: PolarDB for MySQL 8.0, Cluster Edition, 8 núcleos de CPU, 64 GB de memoria.

Configuración

  1. Cree una tabla con 1 millón de filas:

    ./oltp_read_write.lua --mysql-host="Cluster endpoint" --mysql-port="Port number" \
      --mysql-user="Username" --mysql-password="Password" \
      --mysql-db="sbtest" --tables=1 --table-size=1000000 \
      --report-interval=1 --percentile=99 --threads=8 --time=6000 prepare
  2. Simule una carga de trabajo de lectura y escritura:

    ./oltp_read_write.lua --mysql-host="Cluster endpoint" --mysql-port="Port number" \
      --mysql-user="Username" --mysql-password="Password" \
      --mysql-db="sbtest" --tables=1 --table-size=1000000 \
      --report-interval=1 --percentile=99 --threads=8 --time=6000 run
  3. Mantenga un bloqueo MDL al iniciar una transacción y dejarla abierta:

    /* Session 1 */
    BEGIN;
    SELECT * FROM sbtest1;
  4. En una segunda sesión, agregue una columna a la tabla:

    /* Session 2 */
    ALTER TABLE sbtest1 ADD COLUMN d INT;
  5. Repita el cambio de esquema con gh-ost (requiere registro binario; consulte Enable binary logging):

    ./gh-ost --assume-rbr --user="Username" --password="Password" \
      --host="Cluster endpoint" --port="Port number" \
      --database="sbtest" --table="sbtest1" --alter="ADD COLUMN d INT" \
      --allow-on-master --aliyun-rds \
      --initially-drop-old-table --initially-drop-ghost-table --execute

Impacto en las TPS

  • DDL bloqueante (sentencias DDL no bloqueantes deshabilitadas): las TPS caen a cero y permanecen así hasta que termina la sentencia DDL. Disable nonblocking DDL statements

  • DDL no bloqueante: las TPS disminuyen periódicamente mientras la sentencia DDL reintenta obtener el bloqueo, pero nunca llegan a cero. El impacto en el negocio es mínimo. Enable nonblocking DDL statements

  • gh-ost: las TPS caen a cero en picos periódicos. Esta herramienta crea una tabla fantasma, le aplica los cambios y luego renombra atómicamente dicha tabla para reemplazar a la original (el paso de corte). Este proceso requiere un breve bloqueo de tabla, lo que provoca las caídas periódicas de TPS. Use gh-ost to modify the table schema

Comparación de velocidad con 100 millones de filas

Se agregaron columnas a una tabla de 100 millones de filas mediante sentencias DDL no bloqueantes (algoritmos INSTANT, INPLACE y COPY) y gh-ost.

  • Sin carga de trabajo: las sentencias DDL no bloqueantes terminan más rápido que gh-ost. Load-free

  • Carga de trabajo de lectura y escritura: las sentencias DDL no bloqueantes siguen terminando más rápido que gh-ost. read_write.

Las sentencias DDL no bloqueantes mantienen las TPS por encima de cero durante todo el cambio de esquema. Además, terminan más rápido que gh-ost tanto sin carga como con cargas similares a las de producción.

Temas relacionados

Si tiene preguntas sobre las operaciones DDL, contáctenos.