Skip to main content

gh-ost vs pt-online-schema-change

Adela · May 7, 2026

This post is maintained by Bytebase, an open-source database DevSecOps tool that runs MySQL online schema migrations through gh-ost.

gh-ost and pt-online-schema-change are the two tools the MySQL community reaches for when Online DDL can't keep an ALTER online. They solve the same problem with opposite mechanisms — and they fail at the same problem in different ways.

1. Architecture

gh-ost (GitHub Online Schema Transmogrifier)

  • Triggerless. Asynchronous.
  • Tails the binlog to capture writes. Requires Row-Based Replication; typically reads from a replica.
  • Builds a ghost table, copies the source in chunks, replays binlog events into the ghost.
  • Cut-over is a brief metadata lock you trigger explicitly.

gh-ost-general-flow

pt-online-schema-change (Percona Toolkit)

  • Trigger-based. Synchronous.
  • INSERT, UPDATE, DELETE on the source fire triggers that write to the ghost table in the same transaction.
  • Cut-over is an atomic two-table RENAME.
  • Runs on MySQL 5.5+ and supports foreign keys directly.

The two designs trade the same cost in opposite directions.

pt-osc keeps the ghost strictly consistent with the source — no replication lag, no asynchronous gap. Every write on the source pays for that with trigger overhead. The overhead compounds at cut-over: the metadata lock has to coordinate with the trigger-driven writes, and under heavy write traffic that contention is a known operational concern. pt-osc itself ships with innodb_lock_wait_timeout=1 and lock_wait_timeout=60 to position itself as the lock-contention victim rather than the disruptor.

gh-ost keeps writes on the source cheap and pushes consistency work onto the binlog tail. The ghost table trails the source by however long the binlog stream takes — eventual consistency between source and ghost, not per-transaction.

2. Feature Comparison

Featuregh-ostpt-online-schema-change
MechanismBinlog tail (no triggers)DML triggers
Sync modelAsynchronousSynchronous
Source loadLower (reads on replica)Higher (trigger on every write)
Foreign keysNo — drop and recreateYes (--alter-foreign-keys-method)
ReplicationRequires RBRWorks with SBR or RBR
ThrottlingReplication lag, hooks, custom queriesReplication lag, copy speed
Runtime controlUnix socket — throttle, postpone-cut-over-flag-file, retune chunk size, panic to abortRestart-only
Cut-overManual trigger; brief metadata lockAtomic RENAME; metadata lock coordinates with concurrent writes
Cut-over scheduling--postpone-cut-over-flag-file for an off-hours windowCuts over as soon as the copy completes
Unique keyShared NOT NULL unique key with the exact same columns between before/afterA PRIMARY KEY or UNIQUE INDEX on the table
MySQL versions5.7+5.0.2+
ResumableNo — process death loses the migrationYes — --resume, with --history, --nodrop-new-table, --nodrop-triggers on the prior run
Managed lifecycleNo — wrap your own retries, alerting, schedulingNo — same

Two operational properties matter regardless of which you pick. Resumability is uneven — pt-osc supports --resume if the prior run kept the new table and triggers around (--nodrop-new-table, --nodrop-triggers, --history). gh-ost has no equivalent: if the process dies, the migration is lost. Neither tool is managed — monitoring, retries, alerting, and scheduling are yours to wire up around it.

3. Pros and Cons

ToolProsCons
gh-ostLower load on the source. No triggers. Live control via Unix socket. Cut-over you can postpone.No foreign-key support. Requires RBR. MySQL 5.7+. No resume after process death.
pt-online-schema-changeForeign keys preserved. Wide MySQL version support. Resumable with --resume. Conceptually simple.Triggers add load on every write. Lock contention at cut-over under heavy workload. No runtime control.

4. When to Use

Choose gh-ost when:

  • The workload is write-heavy and the source can't afford trigger overhead.
  • You run MySQL 5.7+ with Row-Based Replication.
  • You need throttling, replica testing, or a cut-over window you control.
  • Foreign keys aren't present, or you can drop and recreate them.

Choose pt-online-schema-change when:

  • Tables have foreign keys you can't drop.
  • You're on MySQL 5.5 or 5.6.
  • The workload is light to moderate; trigger overhead won't dominate.
  • You want a simpler setup with no replica dependency.
  • You need resumable migrations (--resume, with --history and --nodrop-*).

5. Bottom Line

Both tools solve the same operational problem: ALTER a large MySQL table while it serves traffic. They diverge on what to do with concurrent writes. gh-ost keeps the source cheap and accepts replication lag plus runtime complexity. pt-osc keeps the ghost strictly consistent and accepts trigger load plus cut-over contention.

The deciding factors are usually concrete:

  • Foreign keys you can't drop → pt-osc.
  • MySQL 5.5 or 5.6 → pt-osc.
  • Heavy write traffic → gh-ost.

Either way, wrap the tool in your own scheduling, retry, and monitoring. Both expect to be operated by a system that handles the lifecycle around them.

Back to blog

Explore the standard for database development