
1. Oracle 死锁进程批量清理从手工 kill 到脚本化执行Oracle 死锁进程批量清理指的是当数据库出现大量阻塞会话时不再逐个执行alter system kill session而是通过一段可复用的 PL/SQL 脚本一次性定位并清理。它适合日常要处理锁等待的 DBA、后端开发以及需要把运维动作沉淀成可复现流程的 SRE。核心检索词就是 oracle 死锁进程、kill session 批量杀进程。我遇到过最典型的一幕业务侧反馈某张订单表更新卡住登录数据库一查v$locked_object发现被几十个会话层层堵住。手工一个个kill session不仅慢还容易漏。更麻烦的是脚本执行环境散落在不同机器上谁在什么时候跑了什么 SQL事后很难追溯。这篇就围绕两件事展开一是给出可直接复制的批量 kill session 脚本并解释为什么初版会报「会话 id 不存在」二是把脚本调用环境统一到 TaoToken 的 Key/API 通道上让每次执行都有记录、可复现。脚本部分会讲清楚权限、验证、排错环境部分会给出可复制的配置片段。需要先说明一个边界kill session是强制中断会话属于有副作用的操作。执行前必须确认锁的持有者确实是异常会话而不是正在跑长事务的正常业务。所以本文的脚本都会带上「先查询、再确认、后执行」的节奏不会一上来就无脑杀。2. TaoToken 前置统一脚本执行环境的 Key 与通道在讲配置之前先说清楚为什么 DBA 脚本也需要一个统一的调用环境。传统做法是把连接串、账号密码写死在脚本里或者放在某台跳板机的环境变量中。时间一长脚本复制来复制去密码泄露风险高而且不同人跑出来的结果对不上排查问题时根本不知道用的是哪个版本。TaoToken 在这里扮演的是「统一 Key/API 通道」的角色。你可以把它理解成一个集中管理模型与工具调用的入口脚本里不再硬编码敏感信息而是通过统一的 API Key 去调用调用记录集中留存。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 入口是 https://taotoken.net/api 。具体到本文场景我会把「生成/校验 kill 脚本」这一步交给模型对话来完成把「长期跑批处理、Agent 化执行」交给 Coding Plan。这样做的价值在于脚本模板本身是固定的但每次锁表的具体情况不同需要动态生成针对性的 SQL这时候模型对话就派上用场。前置准备分三步。第一步拿到 API Key。进入控制台创建 Key地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 创建后在 API Keys 页面管理地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。第二步确认你要用的模型 ID本文示例统一用claude-sonnet-4-5这类通用模型即可具体以控制台可选列表为准。第三步把 Base URL 设为https://taotoken.net/api注意这里不加 UTM 参数保持接口地址干净。如果你更习惯在编辑器里直接对话调试脚本可以走模型对话入口 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 。如果是要把「定时检查锁 生成清理脚本」做成长期任务建议用 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到接口细节先查文档。这里要强调一点TaoToken 管的是「脚本调用环境」和「Key 通道」它不替代你的 Oracle 客户端也不直接连你的生产库。真正执行kill session的仍然是 sqlplus 或你惯用的数据库工具。这个边界必须清楚否则容易误以为把连接串交给它就行。3. 可复制配置批量 kill session 脚本与 settings 片段这一节是全文最核心的部分给出可直接复制的脚本以及配套的配置片段。先讲脚本演进再给最终版。最初很多人会写成这样用游标查出v$locked_object和v$session关联的 sid、serial#然后循环里直接execute immediate拼接 kill 语句。问题在于v$locked_object里同一个 sid、serial# 可能出现多行一个会话锁了多个对象游标就会返回重复记录。第一次 kill 成功后第二次再对同一个 sid、serial# 执行就会报「会话 id 不存在」。所以第一版改进是在 execute 前加一个 count 判断确认会话还在才杀。逻辑是对的但每循环一次就查一次v$locked_object会话多的时候非常慢。最终版直接用group by去重从源头避免重复declare cursor mycur is select b.sid, b.serial# from v$locked_object a, v$session b where a.session_id b.sid group by b.sid, b.serial#; begin for cur in mycur loop execute immediate (alter system kill session || cur.sid || , || cur.serial# || ); end loop; end; /这段脚本的关键点有三个。第一group by b.sid, b.serial#保证每个会话只出现一次避免重复 kill。第二拼接时单引号要写对表示一个单引号字符这是最容易卡住新手的地方。第三alter system kill session需要ALTER SYSTEM权限普通账号跑不了。执行前建议先跑查询版确认要杀的是哪些会话select b.username, b.sid, b.serial#, b.status, b.logon_time, a.object_id from v$locked_object a, v$session b where a.session_id b.sid order by b.logon_time;如果只想杀某个用户的会话可以在游标里加and b.username APP_USER。生产环境强烈建议先加这个过滤条件别一上来就全库杀。接下来是环境配置片段。如果你用 Cline 这类支持 MCP 的工具来管理脚本调用配置里需要写全三件套Base URL、Key、Model ID。下面是一个 JSON 片段示例路径按你本地实际配置文件位置放置{ mcpServers: { taotoken: { url: https://taotoken.net/api, apiKey: sk-你的Key, model: claude-sonnet-4-5 } } }如果你用的是 Codex 风格的auth.json可以这样写{ base_url: https://taotoken.net/api, api_key: sk-你的Key, model_id: claude-sonnet-4-5 }注意 Base URL 统一用https://taotoken.net/api不要带 UTM 参数。Key 从 API Keys 页面获取Model ID 以控制台实际可选为准。这三件套写全脚本调用环境才算配好缺一个都会在请求时报错。4. 验证请求与成功结果执行前后怎么确认脚本写好了配置也配好了接下来要验证。验证分两层一层是数据库侧确认 kill 生效一层是调用通道侧确认请求成功。数据库侧执行脚本前先记录当前锁等待情况select count(*) as locked_cnt from v$locked_object;执行批量 kill 后再查一次select count(*) as locked_cnt from v$locked_object; select sid, serial#, status, event from v$session where status KILLED;正常情况下v$locked_object的数量会明显下降v$session里可能出现状态为KILLED的会话这些会话会在 PMON 清理后消失。如果数量没变说明要么权限不够要么锁的持有者不是这些会话。调用通道侧可以用一个最小请求验证 Key 和 Base URL 是否通。比如通过模型对话入口发一条简单指令让它根据你贴出的锁查询结果生成对应的 kill 脚本。请求成功时你会拿到一段结构完整的 SQL而不是报错。这一步的意义在于确认脚本生成链路是通的后面自动化才有基础。实测下来最容易出问题的是权限。alter system kill session需要 DBA 权限或显式授予的ALTER SYSTEM权限。如果执行时报ORA-01031: insufficient privileges就是权限没给够。授权语句如下按需执行grant alter system to your_user;另一个验证点是会话是否真的被清理。有时候 kill 之后会话状态变成KILLED但迟迟不释放这是因为会话在等回滚。这种情况下可以加immediatealter system kill session sid,serial# immediate;immediate会强制回滚并释放资源但回滚大事务时可能耗时较长生产环境要谨慎。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth这一节把实际会撞到的报错列出来对照处理。401 UnauthorizedKey 不对或没带上。检查apiKey字段是否填了完整 KeyBase URL 是否是https://taotoken.net/api。如果 Key 是从控制台复制的注意别把前后空格带进去。local proxy failed本地代理配置有问题。这类报错通常出现在工具的网络层检查你的工具是否配置了额外的代理地址或者 Base URL 写成了带路径的地址。统一用https://taotoken.net/api这个根地址不要自己拼/v1之类的后缀。reading choices相关报错一般是响应结构解析失败常见于 Model ID 写错或模型不可用。回到控制台确认 Model ID别用记忆里的名字。如果用的是claude-sonnet-4-5确认它在你的账号下可用。OAuth相关报错如果你用的是 Claude Code 这类工具它可能默认走 OAuth 登录流程。要切到 API Key 模式需要在配置里显式指定 Base URL 和 Key而不是依赖登录态。Claude Code 的接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 里面有 Anthropic 兼容配置说明地址是 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude-code-anthropicutm_campaignrewrite 。数据库侧还有两个高频错。ORA-00031: session marked for kill这不是错误是提示会话已被标记等 PMON 清理即可。ORA-00030: User session ID does not exist就是本文开头说的重复 kill 问题用group by去重后不会再出现。还有一个坑是脚本里的单引号拼接。和数量差一个结果完全不同。建议先在测试库跑确认拼接出来的语句是alter system kill session 123,4567这种格式再上生产。6. 把脚本执行沉淀成可复现流程最后说落地。批量 kill session 本身不复杂难的是让它可追溯、可复现。我的做法是把脚本模板固定下来把「根据当前锁情况生成针对性 SQL」这一步交给模型对话把「定时检查 生成报告」交给 Coding Plan。这样每次执行都有输入、有输出、有记录。具体操作上日常临时清理走模型对话入口 https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentchatutm_campaignrewrite 把锁查询结果贴进去让它生成带过滤条件的 kill 脚本。长期跑批或 Agent 化执行走 Coding Plan https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 。Key 统一在 API Keys 页面管理地址是 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。接口细节查文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。一个实用技巧把每次 kill 前的v$locked_object查询结果和执行时间存成日志出问题时能快速回溯是哪个会话、哪个对象、什么时候被清理的。这比事后凭记忆排查靠谱得多。脚本可以复用但判断「该不该杀」永远要人来把关。