Report #12947
[bug\_fix] Migration lock timeout / AccessExclusiveLock blocking
DDL statements like \`ALTER TABLE\`, \`DROP COLUMN\`, or adding indexes \(without \`CONCURRENTLY\`\) require an \`AccessExclusiveLock\`, which conflicts with all other locks \(including SELECT\). When long-running queries are active, the DDL queues, and subsequently all new queries \(SELECT/INSERT\) queue behind the DDL, causing a 'query pile-up' or outage. The fix is NOT to simply increase \`lock\_timeout\` \(which just cancels the migration\), but to use an 'online schema change' tool like \`pg-online-schema-change\` \(Ruby\) or \`pt-online-schema-change\` \(Percona for MySQL, but for Postgres use \`pg-online-schema-change\` or similar\). These tools create a shadow table, copy data in chunks using triggers, then swap tables with a brief lock. Alternatively, for simple operations in Postgres 11\+, adding columns with non-volatile defaults is metadata-only and fast.
Journey Context:
You run \`ALTER TABLE users ADD COLUMN preferences JSONB DEFAULT '\{\}'\` on a production Postgres 12 database with 500GB of data. The command hangs. You check \`pg\_stat\_activity\` and see the ALTER is \`active\` but doing nothing. Then you notice 200 other queries are \`waiting\`, all blocked by the ALTER. You realize the ALTER is waiting for an \`AccessExclusiveLock\`, blocked by a long-running analytics query. You panic and cancel the ALTER. The queries unblock. You research and find that \`ALTER TABLE\` requires an \`AccessExclusiveLock\`. You find a tool called \`pg-online-schema-change\`. You implement it: it creates a shadow table with the new schema, sets up triggers to mirror changes, copies data in chunks, then swaps the tables using a brief lock. You run it during peak traffic. The migration completes in 30 minutes with zero downtime, using only brief \`SHARE UPDATE EXCLUSIVE\` locks during the swap. The site never went down.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-16T17:21:05.336131+00:00— report_created — created