Les tables temporelles, telles que les journaux, les commandes et les historiques, voient leurs données croître d'un côté et devenir obsolètes de l'autre. Elles nécessitent donc l'ajout et la suppression fréquents de partitions. Dans MySQL standard, chaque opération DDL (Data Definition Language) sur une partition bloque tout le trafic DML (Data Manipulation Language) jusqu'à la fin ou l'annulation de l'opération DDL. Cela vous oblige à planifier la maintenance pendant les heures creuses et à accepter des périodes de débit nul.
La maintenance en ligne des partitions résout ce problème en remplaçant les verrous de métadonnées (MDL) au niveau de la table par des verrous MDL au niveau de la partition. Lorsqu'une opération DDL cible une partition spécifique, PolarDB for MySQL acquiert un verrou MDL uniquement sur cette partition. Les autres partitions restent accessibles pour les opérations DML concurrentes. Cette approche élimine les interruptions du trafic DML et vous permet d'exécuter la maintenance des partitions à tout moment.
L'illustration suivante montre comment cette fonctionnalité réduit la contention des verrous lors d'opérations DDL et DML concurrentes.

Prérequis
Avant de commencer, assurez-vous de disposer des éléments suivants :
Un cluster PolarDB for MySQL 8.0 dont la version de révision est 8.0.2.2.0 ou ultérieure. Pour vérifier votre version, consultez la rubrique Interroger la version du moteur.
Le paramètre
partition_level_mdl_enableddéfini surON. Pour obtenir des instructions, consultez la rubrique Spécifier les paramètres du cluster et des nœuds.Le paramètre
transaction_isolationdéfini surREAD-COMMITTEDau niveau global. Pour obtenir des instructions, consultez la rubrique Spécifier les paramètres du cluster et des nœuds.
Activer les MDL au niveau de la partition
Définissez le paramètre partition_level_mdl_enabled sur ON pour activer les verrous MDL au niveau de la partition. Ce paramètre contrôle la granularité des verrous : au lieu de verrouiller la table entière lors d'une opération DDL, PolarDB for MySQL verrouille uniquement la partition concernée.
| Paramètre | Niveau | Description |
|---|---|---|
partition_level_mdl_enabled |
Global | Active les verrous MDL au niveau de la partition. Valeurs valides : ON (activé), OFF (désactivé). |
Redémarrez le cluster après avoir modifié ce paramètre pour que la modification prenne effet.
Opérations prises en charge
La maintenance en ligne des partitions s'applique aux opérations DDL suivantes. L'opération ADD PARTITION est prise en charge pour les tables partitionnées par RANGE et LIST. La prise en charge d'autres opérations DDL et types de partition sera disponible dans une version future.
| Opération | Description |
|---|---|
ADD PARTITION |
Ajoute une nouvelle partition (uniquement pour le partitionnement RANGE et LIST) |
DROP PARTITION |
Supprime une partition existante |
EXCHANGE PARTITION |
Échange les données entre une partition et une table non partitionnée |
REBUILD PARTITION |
Reconstruit une partition sur place |
REORGANIZE PARTITION |
Divise ou fusionne des partitions existantes |
Limitations
Si le niveau d'isolation est défini sur REPEATABLE-READ ou supérieur et que des opérations DDL s'exécutent simultanément, l'erreur suivante peut apparaître :
ERROR HY000: Table definition has changed, please retry transaction
Il s'agit d'un comportement attendu. Cette erreur survient car une instruction DML a accédé à une partition qui vient d'être créée par une opération DDL concurrente. Réessayez la transaction pour résoudre le problème.
Le niveau d'isolation peut également être défini au niveau de la session, et pas seulement globalement.
Exemple d'utilisation
L'exemple suivant utilise deux clients simultanés pour illustrer comment la maintenance en ligne des partitions permet la coexistence des opérations DML et DDL.
-- Client 1: View the current table structure
SHOW CREATE TABLE tr\G
*************************** 1. row ***************************
Table: tr
Create Table: CREATE TABLE `tr` (
`id` int(11) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`purchased` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (year(`purchased`))
(PARTITION p0 VALUES LESS THAN (1990) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (1995) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (2005) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (2010) ENGINE = InnoDB,
PARTITION p5 VALUES LESS THAN (2015) ENGINE = InnoDB) */
1 row in set (0.00 sec)
-- Client 1: Start a transaction and query data
BEGIN;
Query OK, 0 rows affected (0.01 sec)
SELECT * FROM tr WHERE purchased >= '2010-01-01';
+------+----------------+------------+
| id | name | purchased |
+------+----------------+------------+
| 5 | exercise bike | 2014-05-09 |
| 7 | espresso maker | 2011-11-22 |
+------+----------------+------------+
2 rows in set (0.01 sec)
-- Client 2: While client 1's transaction is open, add a new partition and insert data
ALTER TABLE tr ADD PARTITION (PARTITION p6 VALUES LESS THAN (2020));
INSERT INTO tr VALUES (11, 'hope', '2017-11-04'), (12, 'carmen', '2018-06-08');
-- Client 1: Query again in the same transaction — the new partition's data is visible
SELECT * FROM tr WHERE purchased >= '2010-01-01';
+------+----------------+------------+
| id | name | purchased |
+------+----------------+------------+
| 5 | exercise bike | 2014-05-09 |
| 7 | espresso maker | 2011-11-22 |
| 11 | hope | 2017-11-04 |
| 12 | carmen | 2018-06-08 |
+------+----------------+------------+
4 rows in set (0.00 sec)
-- Client 2: Drop an old partition while client 1's transaction is still open
ALTER TABLE tr DROP PARTITION p0;
-- Client 1: Confirm the table structure reflects both changes — p6 added, p0 dropped
SHOW CREATE TABLE tr\G
*************************** 1. row ***************************
Table: tr
Create Table: CREATE TABLE `tr` (
`id` int(11) DEFAULT NULL,
`name` varchar(50) DEFAULT NULL,
`purchased` date DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (year(`purchased`))
(PARTITION p1 VALUES LESS THAN (1995) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (2000) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (2005) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN (2010) ENGINE = InnoDB,
PARTITION p5 VALUES LESS THAN (2015) ENGINE = InnoDB,
PARTITION p6 VALUES LESS THAN (2020) ENGINE = InnoDB) */
1 row in set (0.00 sec)
-- Client 1: Commit the transaction
COMMIT;
Comparaison des performances
Les deux scénarios suivants comparent le débit DML avec et sans maintenance en ligne des partitions.
Scénario 1 : Opération DDL bloquée par une transaction longue
Dans MySQL standard, lorsqu'une opération DDL ne peut pas se poursuivre car une transaction ouverte détient un verrou, l'opération DDL bloque toutes les opérations DML suivantes. Le débit tombe alors à zéro jusqu'à l'annulation de l'opération DDL ou la validation de la transaction.
Avec la maintenance en ligne des partitions activée :
Le débit normal est identique à celui observé lorsque la fonctionnalité est désactivée ; son activation n'ajoute aucune surcharge.
Les transactions longues ne bloquent plus les opérations DDL sur les partitions. Le trafic DML reste stable tout au long de l'opération.

Scénario 2 : Opérations DDL longues
Lorsqu'une opération DDL est lente (par exemple, la reconstruction d'une grande partition), elle peut provoquer de fortes variations du débit DML, même en l'absence de transaction bloquante.
Avec la maintenance en ligne des partitions activée, les opérations DDL longues ont peu d'impact sur le débit DML.

Afficher l'état des verrous MDL
Lorsqu'une opération DDL est en cours d'exécution, interrogez la vue performance_schema.metadata_locks pour afficher l'état des verrous au niveau de la partition.
L'exemple suivant présente la table des verrous lorsque le client 1 détient un verrou de lecture sur la partition p5 et que le client 2 tente ensuite de supprimer cette partition.
-- Client 1: Start a transaction and query partition p5
BEGIN;
SELECT * FROM tr WHERE purchased >= '2010-01-01';
+------+----------------+------------+
| id | name | purchased |
+------+----------------+------------+
| 5 | exercise bike | 2014-05-09 |
| 7 | espresso maker | 2011-11-22 |
+------+----------------+------------+
2 rows in set (0.01 sec)
-- Client 1: Check the lock table
SELECT * FROM performance_schema.metadata_locks;
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| OBJECT_TYPE | OBJECT_SCHEMA | OBJECT_NAME | COLUMN_NAME | OBJECT_INSTANCE_BEGIN | LOCK_TYPE | LOCK_DURATION | LOCK_STATUS | SOURCE | OWNER_THREAD_ID | OWNER_EVENT_ID |
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
| TABLE | test | tr | NULL | 140734887898944 | SHARED_READ | TRANSACTION | GRANTED | sql_parse.cc:6759 | 67 | 17 |
| PARTITION | test | tr | p5 | 140734887896704 | SHARED_READ | TRANSACTION | GRANTED | sql_parse.cc:6502 | 67 | 17 |
| TABLE | performance_schema | metadata_locks | NULL | 140734879511488 | SHARED_READ | TRANSACTION | GRANTED | sql_parse.cc:6759 | 68 | 4 |
| SCHEMA | performance_schema | NULL | NULL | 140734879511648 | INTENTION_EXCLUSIVE | TRANSACTION | GRANTED | dd_schema.cc:108 | 68 | 4 |
+-------------+--------------------+----------------+-------------+-----------------------+---------------------+---------------+-------------+-------------------+-----------------+----------------+
4 rows in set (0.02 sec)
La sortie affiche deux verrous détenus par le thread 67 (client 1) : un verrou SHARED_READ au niveau de la table sur tr et un verrou SHARED_READ au niveau de la partition sur p5 (après élagage des partitions). La colonne OWNER_THREAD_ID identifie le thread qui détient le verrou.
-- Client 2: Attempt to drop partition p5 — this enters a waiting state
-- because client 1 still holds a SHARED_READ lock on p5
ALTER TABLE tr DROP PARTITION p5;
-- Confirm the DDL is waiting for the partition-level MDL
SHOW PROCESSLIST;
+----+-----------------+-----------+------+---------+------+-------------------------------------+----------------------------------+
| Id | User | Host | db | Command | Time | State | Info |
+----+-----------------+-----------+------+---------+------+-------------------------------------+----------------------------------+
| 4 | event_scheduler | localhost | NULL | Daemon | 1550 | Waiting on empty queue | NULL |
| 8 | root | localhost | test | Sleep | 426 | | NULL |
| 9 | root | localhost | NULL | Query | 0 | starting | SHOW PROCESSLIST |
| 10 | root | localhost | test | Query | 10 | Waiting for partition metadata lock | ALTER TABLE tr DROP PARTITION p5 |
+----+-----------------+-----------+------+---------+------+-------------------------------------+----------------------------------+
4 rows in set (0.00 sec)
La colonne State affiche Waiting for partition metadata lock lorsqu'une opération DDL est mise en file d'attente derrière un verrou au niveau de la partition. Pour débloquer l'opération DDL, validez ou annulez la transaction de la session bloquante. Identifiez la session bloquante à l'aide de l'OWNER_THREAD_ID issu de la requête sur metadata_locks, puis validez ou annulez la transaction de cette session.
-- The DROP PARTITION on client 2 proceeds automatically after client 1 commits
Suivre les opérations de maintenance en ligne des partitions
Utilisez la variable d'état Online_altered_partition pour connaître le nombre d'opérations de maintenance en ligne des partitions exécutées.
SHOW STATUS LIKE 'Online_altered_partition';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| Online_altered_partition | 2565 |
+--------------------------+-------+
1 row in set (0.00 sec)
Vidéo d'opération
Démonstration — Verrouillage des métadonnées au niveau de la partition (MDL) pour PolarDB for MySQL