当前位置:首页 > 问答 > 正文

ORA-31478报错导致LogMiner会话无法分离,远程帮忙修复故障全过程分享

那天下午,我正在处理日常工作,突然接到一位朋友的紧急电话,他的声音听起来非常焦急,说他们生产库的一个核心数据同步环节卡住了,报了一个从来没见过的错误,LogMiner的会话怎么也停不下来,让我赶紧远程帮忙看看。

我立刻连上了他们的服务器,我让他描述了一下问题现象,他说,为了做数据同步,他们使用Oracle的LogMiner来解析归档日志,但是当同步任务完成后,想要正常结束(用DBMS_LOGMNR.END_LOGMNR过程)这个LogMiner会话时,数据库就一直报错,会话就像被“粘”住了一样,无法分离,他尝试了几次,每次都报同样的错:ORA-031478。

ORA-31478报错导致LogMiner会话无法分离,远程帮忙修复故障全过程分享

我让他把具体的错误信息发给我,错误信息很明确,ORA-31478: 使用补充日志数据的LogMiner会话无法用当前参数分离”。(来源:Oracle官方文档ORA-31478错误描述)这个错误代码我之前有印象,但没实际处理过,我告诉他别慌,这个错误通常意味着开始LogMiner会话(用DBMS_LOGMNR.START_LOGMNR过程)时,使用的参数和现在试图结束它时的参数不匹配。

为了确认情况,我让他查询了当前活动的LogMiner会话信息,我们使用了类似这样的语句:“SELECT * FROM V$LOGMNR_SESSION;”。(来源:Oracle数据字典视图V$LOGMNR_SESSION)查询结果出来一看,果然,当前确实存在一个活跃的会话,关键是要看这个会话启动时使用的参数,特别是OPTIONS参数。

ORA-31478报错导致LogMiner会话无法分离,远程帮忙修复故障全过程分享

朋友回忆说,他启动LogMiner时,为了捕获更详细的数据变化信息,确实添加了一个叫做“补充日志”的选项,大概的参数是DBMS_LOGMNR.ADD_LOGMNR_OPTIONS之类的,我告诉他,问题很可能就出在这里,ORA-31478错误的核心原因就是:当你启动会话时启用了补充日志(这是一种更高级的日志记录模式),那么在结束会话时,也必须在DBMS_LOGMNR.END_LOGMNR过程中明确指定同样的选项,告诉数据库“我要结束的是一个使用了补充日志的会话”,否则数据库出于数据一致性的考虑,会拒绝你的结束请求。(来源:Oracle官方文档对DBMS_LOGMNR.END_LOGMNR过程的说明)

找到了方向,接下来就是修复,修复步骤其实很简单,怎么开始的,就怎么结束”。

ORA-31478报错导致LogMiner会话无法分离,远程帮忙修复故障全过程分享

第一步,我让他再次确认V$LOGMNR_SESSION视图中记录的SESSION_ID(或者类似标识符)以及启动时使用的OPTIONS值,他确认了SESSION_ID是1,OPTIONS值里面包含了代表补充日志的标识。

第二步,就是最关键的一步,重新执行结束命令,但这次要带上正确的参数,我让他不要再用空的DBMS_LOGMNR.END_LOGMNR了,而是使用完整的命令,把之前启动时用到的选项原封不动地再写进去,具体的命令类似于: BEGIN DBMS_LOGMNR.END_LOGMNR(options => DBMS_LOGMNR.ADDFILE_OPTION + DBMS_LOGMNR._THAT_SPECIFIC_SUPPLEMENTAL_OPTION_HE_USED); END; / (注:这里的选项名称是示意,实际需要根据他启动时使用的具体选项来定)

他小心翼翼地执行了我给的命令,执行完成后,屏幕上没有报错,只显示了“PL/SQL procedure successfully completed.”,他有点不敢相信,又立刻去查询了一次V$LOGMNR_SESSION视图,发现之前那个“粘”着的会话果然消失了!

问题解决了,朋友长舒一口气,我趁热打铁,给他总结了一下这次故障的教训,核心就两点:第一,要养成好习惯,记录下每次启动LogMiner时使用的完整参数,最好写在脚本里,这样结束的时候直接复制粘贴就不会错,第二,要理解ORA-31478这个错误并不可怕,它其实是Oracle的一种保护机制,防止误操作导致问题,本质上是要求你的操作有始有终,前后一致。

这次远程协助虽然只花了不到半小时,但因为是在生产环境,过程还是挺紧张的,通过这个实际的案例,我们都对LogMiner的这个特性有了更深刻的理解,以后遇到类似问题,就知道该从哪里下手了。