Online schema changes

MySQL · Advanced · 14 min

Altering a big table the wrong way can block writes for hours or stall the whole application on a metadata lock.

InnoDB's online DDL can change many schemas without blocking writes. Request the algorithm explicitly so MySQL errors out instead of silently choosing a blocking one:

  • `ALGORITHM=INSTANT`: changes metadata only, finishing in milliseconds regardless of table size. Adding a column (anywhere, since 8.0.29), dropping a column (8.0.29+), renaming a column, setting a default, and extending some ENUM definitions.
  • `ALGORITHM=INPLACE, LOCK=NONE`: rebuilds or modifies the table while allowing concurrent reads and writes, e.g. adding a secondary index. It still does heavy I/O, and changes made meanwhile are buffered in an online log that must be applied at the end.
  • `ALGORITHM=COPY`: copies the whole table and blocks writes — e.g. changing a column's data type.

Every DDL needs an exclusive metadata lock (MDL) briefly at the start and end. If a long transaction has touched the table, the DDL waits — and every new query on the table queues behind the waiting DDL. Set lock_wait_timeout low for the DDL session and check performance_schema.metadata_locks or SHOW PROCESSLIST ("Waiting for table metadata lock").

On replicas, an INPLACE alter replays only after it completes on the source, causing replication lag. For huge tables, tools like gh-ost and pt-online-schema-change copy into a shadow table in throttled chunks and swap it in; they control load and lag better.

Example

CREATE TABLE orders (id BIGINT PRIMARY KEY, customer_id BIGINT, note VARCHAR(100));

SET SESSION lock_wait_timeout = 5;          -- don't queue forever on the MDL

ALTER TABLE orders ADD COLUMN source VARCHAR(20) NULL, ALGORITHM = INSTANT;
-- Query OK, 0 rows affected (0.01 sec)

ALTER TABLE orders ADD INDEX idx_customer (customer_id),
      ALGORITHM = INPLACE, LOCK = NONE;     -- reads and writes continue

ALTER TABLE orders MODIFY note TEXT, ALGORITHM = INPLACE, LOCK = NONE;
-- ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported.
--   Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.

SELECT object_name, lock_type, lock_status, owner_thread_id
FROM performance_schema.metadata_locks WHERE object_name = 'orders';

Remember

  • Specify ALGORITHM (and LOCK) so MySQL refuses blocking plans
  • INSTANT for many column changes; INPLACE LOCK=NONE for indexes
  • Metadata lock waits queue every query behind the DDL; set lock_wait_timeout

Watch out for

  • Running ALTER TABLE while a long transaction holds the table, freezing all traffic behind the metadata lock.

Check yourself

  1. Why specify ALGORITHM=INPLACE, LOCK=NONE explicitly?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: dev.mysql.com/doc/refman/8.4/en/innodb-online-ddl.html

Builds on

Unlocks

Nothing builds on this yet.