# 修改表结构为什么会导致库挂了
场景重现
# 时序展示
| session A | session B | session C | session D |
|---|---|---|---|
| begin; select * from t where id =? | |||
| begin; select * from t where id =? | |||
| alter table t add column age int(3) not null | |||
| begin; select * from t where id =? |
以上时序中session C需要获取到MDL写锁而要等待其他事务释放MDL读锁, 在等待锁释放期间, session D等之类的其他事务又需要对表进行操作进而申请MDL读锁, 此时数据库连接都会被阻塞, 如果应用程序有重起连接重试的场景或者突然高并发的情况发生, 都会导致数据库连接瞬间爆满, 最终数据库挂了.
# 解决方案
# 1. 停掉应用程序修改热点表数据结构
# 2. 避免长事务或kill掉长事务再执行
# 3. 设置DDL语句等待时间, 尝试拿锁, 尽量避免阻塞其他线程
如果未拿到锁超时, 可以下次再重试执行.
# AliSQL分支提供的此功能, 已被MariaDB合并.
ALTER TABLE tbl_name NOWAIT add column ...;
ALTER TABLE tbl_name WAIT N add column ...;