All Products
Search
Document Center

PolarDB:Error executing a DDL statement: Failed to obtain a metadata lock

Last Updated:Mar 28, 2026

DDL operations in PolarDB for MySQL can fail when a read-only node holds an active metadata lock (MDL). This topic explains why this happens and how to resolve it.

Error messages

ERROR HY000: Fail to get MDL on replica during DDL synchronize
ERROR HY000: Fail to get table lock on replica; you can 'set polar_support_mdl_sync_preemption = ON' and try restarting transaction

Root cause

When the primary node runs a DDL operation, it first acquires an MDL on the affected table, then writes a redo log entry. Each read-only node parses that redo log entry and attempts to acquire an MDL on the same table. If a read-only node has ongoing queries or uncommitted transactions that already hold the MDL, it cannot acquire the lock and sends an error back to the primary node. The primary node then rolls back the DDL and returns one of the errors above.

Solutions

Choose the approach that best fits your situation:

SituationRecommended approach
DDL operations frequently fail due to long-running reads on read-only nodesEnable preemptive DDL
Uncommitted transactions are blocking DDL and you need a persistent fixEnable the polar_slave_work_on_nonblock_mdl_mode parameter
You need to unblock DDL immediatelyIdentify and kill the blocking session (see Diagnose and kill blocking sessions)
A specific transaction is blocking DDL and can safely be committed or rolled backCommit or roll back the uncommitted transaction on the read-only node

Enable preemptive DDL

The preemptive DDL feature lets DDL operations preempt ongoing reads on read-only nodes, preventing them from blocking DDL synchronization. For setup instructions, see Preemptive DDL.

Prevent long-running transactions from blocking DDL

Enable the polar_slave_work_on_nonblock_mdl_mode parameter on the read-only node. This prevents long-running uncommitted transactions from blocking DDL operations. For details, see Prevent long-running transactions on read-only nodes from blocking DDL operations.

Use Session Manager to find and end abnormal sessions

  1. Log on to the PolarDB console. In the left navigation pane, choose Diagnostics and Optimization > Quick Diagnostics.

  2. On the Session Manager tab, check for abnormal sessions.

    image

  3. Click View Details in the anomaly section to review the session details.

    image

  4. End sessions with long-running uncommitted transactions. For other abnormal sessions, optimize or end them as needed.

For more information, see Session Manager.

Contact us

If you have any questions about DDL operations, please contact technical support.

Diagnose and kill blocking sessions

Use Polar Performance Schema to query the MDL status on the target table, identify the blocking thread, and kill it.

Step 1: Check whether Polar Performance Schema is enabled

Check in one of two ways:

Option A — PolarDB console:

Log on to the PolarDB console. In the left navigation pane, choose Settings and Management > Parameter Settings. Find the loose_polar_performance_schema parameter and check its value.

All cluster parameters in the console are prefixed with loose_ for MySQL configuration file compatibility. The loose_polar_performance_schema parameter in the console corresponds to the polar_performance_schema variable.
image

Option B — SQL:

SHOW VARIABLES LIKE 'polar_performance_schema';

Expected output:

+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| polar_performance_schema | ON    |
+--------------------------+-------+

Step 2: Query MDL status and kill the blocking thread

Follow the steps for your configuration:

Polar Performance Schema is ON

Query performance_schema.metadata_locks to identify which thread holds or is waiting for the MDL on your target table.

  1. Use a node hint to target the read-only node and run the query. Replace pi-bp10k7631d6k3**** with your actual read-only node ID.

    • The test01/t1 table has a SHARED_READ lock that is GRANTED — held by an active query or uncommitted transaction.

    • The test/t1 table has an EXCLUSIVE lock that is PENDING — this is the DDL waiting to acquire the lock.

    /*force_node='pi-bp10k7631d6k3****'*/ SELECT t.PROCESSLIST_ID, m.OBJECT_TYPE, m.OBJECT_SCHEMA, m.OBJECT_NAME, m.LOCK_TYPE, m.LOCK_DURATION, m.LOCK_STATUS FROM performance_schema.metadata_locks m LEFT JOIN performance_schema.threads t ON m.owner_thread_id=t.thread_id;

    Sample result: In this example: The PROCESSLIST_ID column gives you the connection ID to kill.

    image

  2. Kill the blocking thread using the same node hint:

    /*force_node='pi-bp10k7631d6k3****'*/ kill 536976473;
Note

If the uncommitted transaction on the read-only node is critical, do not kill it. Wait for the transaction to complete before retrying the DDL operation.

If the kill command fails with ERROR 1094 (HY000): Unknown thread id: xxx, the thread no longer exists. If you continue to experience issues, contact technical support.

Polar Performance Schema is OFF

Query information_schema.innodb_trx to identify uncommitted transactions on the read-only node.

  1. Use a node hint to target the read-only node and run the query. Replace pi-bp10k7631d6k3**** with your actual read-only node ID.

    /*force_node='pi-bp10k7631d6k3****'*/ SELECT * FROM information_schema.innodb_trx\G
  2. Interpret the result based on which scenario applies: DDL blocked by a large query Sample result: A row appears for the t1 table, indicating the current connection holds the MDL. Use trx_mysql_thread_id as the thread ID to kill. DDL blocked by a large transaction Sample result: The transaction (for example, ID 537247177) is uncommitted, but trx_query is empty — you cannot tell from the query alone whether it holds the MDL. Check trx_started: if the timestamp is much earlier than the current time, this transaction is likely holding the MDL.

    image

    image

  3. Kill the blocking thread:

    /*force_node='pi-bp10k7631d6k3****'*/ kill 537247177

FAQ

Why doesn't `kill` stop the session immediately?

When you run kill, the database marks the session for termination and waits for the kernel to complete the stop. If the session has an active transaction, the session stops only after the transaction finishes rolling back — which can take time for large transactions.

To check whether a session is still rolling back, run:

SELECT TRX_ID, TRX_STATE, TRX_STARTED, TRX_QUERY FROM information_schema.innodb_trx WHERE trx_mysql_thread_id = <Session ID>;

If TRX_STATE is ROLLING BACK, wait for the rollback to finish. The kill completes automatically when the rollback is done.

What's next