Impacto de la mejora de la estrategia de bloqueos MDL en GreatSQL sobre la ejecución

  1. Estrategia de bloqueos MDL en GreatSQL

En GreatSQL, la gestión de bloqueos de metadatos se centraliza en la clase MDL_lock_strategy. Esta clasifica los bloqueos según su alcance: los de scope se aplican a objetos globales como GLOBAL, COMMIT, TABLESPACE o BACKUP_LOCK, mientras que los de object se refieren a tablas del diccionario de datos (DD). El siguiente análisis se centra en estos últimos.

Para cada tabla, el motor mantiene tres estructuras de control:

  • m_fast_path_state: bitmap que cuenta los bloqueos obtenidos por la ruta rápida (fast path).
  • m_granted: cola de bloqueos ya concedidos mediante la ruta lenta (slow path).
  • m_waiting: cola de bloqueos pendientes de conceder.

Los bloqueos se dividen en dos grupos según su impacto:

  • Ruta rápida (unobtrusive): S, SH, SR y SW. Se contabilizan en m_fast_path_state sin almacenar información individual.
  • Ruta lenta (obtrusive): SU, SRO, SNW, SNRW y X. Se gestionan a través de las colas m_granted y m_waiting.
  1. Niveles de política y prevención de inanición

La concesión de un bloqueo se evalúa en MDL_lock::can_grant_lock. Se requiere que no haya bloqueos incompatibles en m_granted ni bloqueos de mayor prioridad en m_waiting.

Para evitar que los bloqueos de baja prioridad esperan indefinidamente, el motor alterna entre cuatro matrices de compatibilidad en la cola de espera:

  • m_granted_incompatible: matriz base sobre la cola m_granted.
  • m_waiting_incompatible[0]: política normal de espera.
  • m_waiting_incompatible[1]: se activa cuando m_piglet_lock_count >= max_write_lock_count.
  • m_waiting_incompatible[2]: se activa cuando m_hog_lock_count >= max_write_lock_count.
  • m_waiting_incompatible[3]: se activa cuando la suma de bloqueos hog y piglet alcanza el umbral.

Los tipos hog (X, SNRW, SNW) son muy incompatibles y tienden a acaparar la tabla; los piglet (SW) tienen una priordiad intermedia. El contador correspondiente determina cuándo se eleva o se reduce la política activa.

  1. Semántica de los modos de bloqueo

Los modos más relevantes para objetos de tabla son:

  • S: lectura de metadatos sin lectura de filas.
  • SH: lectura de metadatos con prioridad sobre operaciones de escritura.
  • SR: lectura de metadatos y de filas dentro de una transacción.
  • SW: lectura de metadatos y actualización de filas.
  • SWLP: como SW, pero con prioridad reducida.
  • SU: bloqueo actualizable; permite lectura/escritura concurrrente y puede ascender a SNW, SNR o X.
  • SRO: solo lectura de metadatos y filas; bloquea modificaciones y DDL.
  • SNW: bloquea escrituras ajenas; puede ascender a X.
  • SNRW: bloquea lecturas y escrituras ajenas.
  • X: bloqueo exclusivo para modificaciones de esquema y datos.
  1. Efecto práctico de max_write_lock_count

Cuando varios hilos compiten por la misma tabla, el valor de max_write_lock_count decide cuál matriz de espera está activa y, por tanto, qué solicitud se atiende primero.

Para ilustrarlo, se crea una tabla de ejemplo con nombres de columna distintos:

CREATE TABLE `datos` (
  `id` int NOT NULL,
  `txt` varchar(100) DEFAULT NULL,
  `ts` timestamp(3) NULL DEFAULT NULL,
  `obs` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

INSERT INTO datos (id, txt, ts, obs) VALUES
  (1, 'aaaa', '2021-01-19 03:14:07.123', 'init'),
  (2, NULL,   '2022-01-19 03:14:07.123', NULL),
  (3, 'bbbb', NULL,                    NULL),
  (4, NULL,   NULL,                    NULL),
  (15,'cccc', '2025-01-19 03:14:07.123','last');

4.1. Caso: max_write_lock_count = 100

Con seis sesiones concurrentes y el umbral alto, el contador m_piglet_lock_count no supera el límite, por lo que se mantiene la política 0. Bajo esta política, SW tiene mayor prioridad que SRO. Cuando la primera sesión confirma su transacción, los bloqueos SW pendientes se conceden antes que las lecturas SRO restantes.

4.2. Caso: max_write_lock_count = 1

Tras la concesión de varios bloqueos SRO, el contador de piglet alcanza el umbral y la política de espera asciende a 1. En esta política, SW tiene menor prioridad que SRO, por lo que, tras el COMMIT de la primera sesión, los bloqueos SRO en espera se conceden antes que los SW. Cuando ya no quedan SRO pendientes, la estrategia vuelve a bajar a 0.

El estado de los bloqueos se puede observar con una consulta como la siguiente:

SELECT *
FROM performance_schema.metadata_locks
WHERE object_schema = 'demo'
  AND object_name = 'datos';

El resultado mostrará, tras la escalada de política, varios bloqueos SHARED_READ_ONLY en estado GRANTED mientras un SHARED_WRITE permanece en estado PENDING.

  1. Momentos de cambio de política

La función MDL_lock::reschedule_waiters reevalúa la política activa cuando ocurre alguno de estos eventos:

  • Se elimina un ticket de m_granted o m_waiting.
  • Otro hilo solicita un bloqueo que provoca una escalada de la estrategia.
  • Un bloqueo se libera o se degrada.
  1. Consideraciones operativas

El parámetro max_write_lock_count actúa como regulador de la inanición de bloqueos. Disminuirlo permite que los bloqueos de menor prioridad avancen antes, pero puede retrasar operaciones de mayor prioridad y alterar el rendimiento de cargas concurrentes. Incrementarlo mantiene el orden habitual a favor de los bloqueos más agresivos. La elección del valor debe ajustarse al comportamiento esperado de cada carga de trabajo.

Etiquetas: GreatSQL MDL max_write_lock_count bloqueos de metadatos InnoDB

Publicado el 7-2 23:32