引言
在数据库管理过程中,执行 alter table
添加字段(ddl 操作)时,可能会遇到操作卡死的情况。这不仅影响业务正常运行,还可能导致锁表、连接池耗尽等问题。本文将深入分析 ddl 操作卡死的原因,并提供不同数据库(mysql、oracle、postgresql、sql server)的解决方案,同时给出预防措施,帮助 dba 和开发人员高效应对此类问题。
1. ddl 操作为什么会卡死?
ddl(data definition language)操作如 alter table
修改表结构时,数据库通常需要获取元数据锁(mdl)或表锁,以确保数据一致性。卡死的主要原因包括:
- 长事务阻塞:某个事务长时间持有锁,导致 ddl 操作等待。
- 大表操作:表数据量过大,ddl 执行时间过长,甚至超时。
- 并发冲突:多个会话同时修改同一张表,导致死锁。
- 资源不足:数据库 cpu、i/o 或内存资源不足,导致 ddl 执行缓慢。
2. mysql 如何终止卡住的 ddl 操作?
(1) 查找并终止 ddl 进程
-- 查看当前运行的进程 show processlist; -- 找到对应的 ddl 操作(如 alter table) +----+------+-----------+------+---------+------+-----------------------------+----------------------------------+ | id | user | host | db | command | time | state | info | +----+------+-----------+------+---------+------+-----------------------------+----------------------------------+ | 5 | root | localhost | test | query | 120 | altering table | alter table users add column ... | +----+------+-----------+------+---------+------+-----------------------------+----------------------------------+ -- 终止该进程 kill 5;
(2) 使用 online ddl(mysql 5.6+)
-- 采用 inplace 算法,减少锁表时间 alter table users add column age int, algorithm=inplace, lock=none;
(3) 强制重启(极端情况)
如果 ddl 完全卡死且无法终止,可能需要重启 mysql:
sudo systemctl restart mysql
3. oracle 如何终止卡住的 ddl 操作?
(1) 查找 ddl 会话
select sid, serial#, username, sql_id, status from v$session where sql_id in ( select sql_id from v$sql where sql_text like 'alter table%' );
(2) 终止会话
alter system kill session 'sid,serial#' immediate;
(3) 强制终止(如果会话无法终止)
-- 查找操作系统进程 id(spid) select p.spid, s.sid, s.serial# from v$session s, v$process p where s.paddr = p.addr and s.sid = [sid]; -- 在操作系统层面终止 kill -9 [spid]
4. postgresql 如何终止卡住的 ddl 操作?
(1) 查找 ddl 进程
select pid, query, state, age(clock_timestamp(), query_start) from pg_stat_activity where query like 'alter table%';
(2) 终止进程
-- 尝试优雅终止 select pg_cancel_backend(pid); -- 强制终止(如果 pg_cancel_backend 无效) select pg_terminate_backend(pid);
(3) 防止 ddl 卡死
postgresql 支持 concurrently
方式创建索引,减少锁冲突:
create index concurrently idx_name on users(name);
5. sql server 如何终止卡住的 ddl 操作?
(1) 查找 ddl 会话
select session_id, command, text, status, blocking_session_id from sys.dm_exec_requests cross apply sys.dm_exec_sql_text(sql_handle) where command = 'alter table';
(2) 终止会话
kill [session_id];
(3) 使用 online ddl(sql server 2016+)
-- 在线添加列 alter table users add age int with (online = on);
6. 如何预防 ddl 操作卡死?
(1) 选择合适的时间执行 ddl
- 在业务低峰期(如凌晨)执行。
- 避免在高峰期修改大表结构。
(2) 使用 online ddl 工具
- mysql:
pt-online-schema-change
(percona toolkit) - postgresql:
create index concurrently
- sql server:
with (online = on)
(3) 分批执行 ddl
- 对大表分批次添加字段,避免长时间锁表。
(4) 监控长事务
-- mysql 监控长事务 select * from information_schema.innodb_trx where time_to_sec(timediff(now(), trx_started)) > 60;
(5) 设置超时时间
-- mysql 设置 ddl 超时 set session lock_wait_timeout = 60; -- 60秒超时
7. 总结
数据库 | 查找 ddl 会话方法 | 终止方法 | 预防措施 |
---|---|---|---|
mysql | show processlist | kill pid | algorithm=inplace |
oracle | v$session | alter system kill session | 避免高峰执行 |
postgresql | pg_stat_activity | pg_terminate_backend | create index concurrently |
sql server | sys.dm_exec_requests | kill session_id | with (online = on) |
关键点:
- 优先使用 online ddl,减少锁表时间。
- 监控长事务,避免阻塞 ddl。
- 分批执行,降低对业务的影响。
- 设置超时,防止无限等待。
通过合理的方法,可以高效解决 ddl 卡死问题,保障数据库稳定运行。
以上就是数据库ddl操作卡死问题原因、解决与预防指南的详细内容,更多关于数据库ddl操作卡死的资料请关注代码网其它相关文章!
发表评论