是,MyISAM引擎下ALTER TABLE全程锁整表,读写全阻塞;InnoDB虽支持Online DDL,但加索引、改列类型等操作仍需短暂MDL排他锁,卡顿常因长事务阻塞MDL获取。
大概率是。MyISAM引擎下ALTER TABLE会全程锁整张表,读写全阻塞,锁表时间 = 表数据量 × 拷贝速度,大表动辄几分钟甚至几小时。先确认引擎:
SHOW CREATE TABLE your_table_name; —— 如果看到ENGINE=MyISAM,这就是根因。
mysqldump -u root -p db table > backup.sql导出,再建ENGINE=InnoDB新表导入pt-online-schema-change,它通过触发器+影子表实现无锁改结构,但需确保主键存在、无外键依赖InnoDB本身支持Online DDL,但某些操作仍需短暂排他元数据锁(MDL),比如加索引、改列类型、或修改主键。锁久不是因为拷贝数据慢,而是卡在等MDL释放。
查谁在占着MDL:
SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = 'your_db' AND OBJECT_NAME = 'your_table';
LOCK_STATUS = 'PENDING'的行,说明有线程在等锁OWNER_THREAD_ID去performance_schema.threads里找对应SQL和状态SELECT ... FOR UPDATE后挂起、或另一个ALTER TABLE正在跑OPTIMIZE TABLE对InnoDB本质是ALTER TABLE ... FORCE,会重建表并整理碎片——它不只锁表,还会触发大量行锁和间隙锁,尤其当表有活跃写入时。
别把它当日常维护手段。真实场景中,只有满足以下全部条件才值得跑:
DATA_FREE远大于实际数据(SHOW TABLE STATUS LIKE 'table_name';查)替代方案更安全:ALTER TABLE t ENGINE=InnoDB;(显式重建) + ANALYZE TABLE t;(更新统计信息)。
核心原则:不让DDL和业务SQL抢同一把MDL。线上环境必须绕开高峰期,并提前预判阻塞链。
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW() - trx_started) > 60; —— 干掉运行超1分钟的事务SHOW SLAVE STATUSG确认Seconds_Behind_Master接近0再操作SET lock_wait_timeout = 3;临时降低MDL等待阈值,让阻塞快速失败而非死等performance_schema.events_statements_current中LOCK_TIME突增 + STATEMENT含ALTER/OPTIMIZE
真正难处理的是那种“刚改完表,下游服务就报Lock wait timeout exceeded”的情况——往往说明业务代码里混了DDL依赖,或者误把OPTIMIZE当缓存清理用了。这类耦合得从应用层切开,而不是调参硬扛。