如果您正在使用 Debezium 的 Oracle 连接器,很可能您已经遇到过关于“在事务日志中找不到 SCN”的臭名昭著的异常。在这篇博文中,我们将不仅讨论这个异常的含义,还会探讨其原因以及您应该采取的故障排除步骤。
您应该了解什么……
在我们讨论异常的含义和如何进行故障排除之前,重要的是要对我们将在文章后面使用的一些技术细节有所了解。
什么是SCN?
系统更改号(SCN)是Oracle用于排序更改的内部机制。您可以将其视为用于跟踪数据库中更改进度的逻辑时间戳。每次提交、每次对表的更改、每次DDL操作——所有这些都会被分配一个SCN。
关于SCN需要考虑的重要事项
-
它们是单调递增的,但在不同上下文之间并非全局唯一。例如,在Oracle RAC中,多个重做线程(我们稍后会讨论)可能具有重叠的SCN范围。此外,Oracle被允许将相同的SCN分配给多个更改。
-
它们对Oracle LogMiner至关重要,因为Oracle使用SCN来定位日志挖掘会话的开始和结束点。
-
Debezium在流式处理过程中使用SCN作为恢复点,确保在连接器重新启动时不会丢失或重复更改。
重做日志——在线与归档
Oracle将所有事务写入称为重做日志的事务日志中。这些日志有两种形式:
在线重做日志
这些是活动的、循环的日志,由Oracle日志写入器(LGWR)进程实时写入。它们的尺寸是有限的,一旦其中的所有更改都被安全地归档,它们就会被覆盖。
归档重做日志
当启用归档时,Oracle会在在线重做日志被覆盖之前将其完整副本复制到归档目标。这些对于以下情况至关重要:
-
长时间运行的查询或事务
-
按时间点恢复
-
像Debezium这样的下游系统,需要历史日志数据
重做线程
无论您是将Oracle部署为独立实例还是使用Oracle RAC,每个Oracle实例都会写入自己的重做线程。虽然SCN是全局递增的,但每个重做线程维护一个逻辑上的时间顺序更改序列,这些更改发生在该特定实例上。实际上,这意味着:
-
一个重做线程(T1)可能包含的事务更改,在逻辑上发生在另一个重做线程(T2)之后,即使SCN看起来是交错的。
-
Debezium以及LogMiner,需要访问所有重做线程中的日志,才能正确地重构数据库中事务的全局顺序。
-
任何重做线程的丢失或未归档的重做日志都可能导致间隙,Debezium在Oracle执行日志切换(我们稍后会详细讨论)时通过执行日志一致性检查来防止这种情况。
如何排查“找不到SCN”错误?
在Debezium连接器的生命周期中,有几个点Oracle连接器可能会报告找不到日志中的特定SCN。让我们分解一下这种情况发生在哪里以及如何排查每种情况。
日志位置验证
当Debezium Oracle连接器启动时,其中一个首要步骤是验证基于偏移量中最后一个已知SCN的恢复位置是否仍然有效。为此,Debezium会将存储的偏移量SCN与数据库重做日志(在线或归档)中最早可用的SCN进行比较。
逻辑很简单:
-
如果最早SCN ≤ 偏移量SCN,则位置有效。
-
如果最早SCN > 偏移量SCN,则位置无效,Debezium将抛出一个错误,表明找不到SCN。
为什么SCN会变得无效?
有几个常见的原因:
- 归档日志保留时间短
-
Oracle归档策略可能会比Debezium处理它们的速度更快地清除日志。
- 连接器长时间停机
-
如果连接器离线时间超过日志保留期,所需的日志可能不再存在。
- 捕获和未捕获表之间的活动偏差
-
即使Debezium没有捕获这些表,全局SCN也会随着事务的发生而增加。这可能导致偏移量中的SCN过时。
您可以做什么
根据用例,您可以执行以下操作:
- 归档日志过早删除
-
与DBA合作,增加保留窗口或配置一个具有更长保留期的次要归档目标。确保Debezium能够访问所有重做线程的在线和归档日志。
- 连接器离线时间过长
-
如果可能,请DBA恢复丢失的归档日志。恢复后,Debezium应在不更改的情况下恢复。如果无法恢复:
- 表活动不成比例
-
使用
heartbeat.interval.ms和heartbeat.action.query配置心跳,以确保即使没有捕获到任何更改,SCN也能正常推进。请确保心跳查询中使用的表包含在连接器的包含列表中。
重做线程一致性
从Debezium 2.7开始,引入了一个更复杂的_一致性检查_,以确保所有重做线程的日志挖掘都是可靠的。这个过程称为重做线程一致性。
如果您看到类似以下的错误,则说明您遇到了此检查。
Redo Thread 1 is inconsistent; an archive log with sequence 12345 is not available Debezium检查什么
在开始挖掘之前,Debezium会查询可用的日志并验证以下内容:
-
至少有一个线程拥有包含所需SCN的日志。
-
对于每个线程,日志序列必须是连续的(无间隙),直到
V$THREAD中的最新序列号。 -
所有重做线程都必须通过此检查。
-
处于
OPEN状态的线程(通常是活动实例)比处于CLOSED状态的线程受到更严格的标准。
如果任何重做线程未能通过此一致性检查,Debezium将短暂暂停,重新查询日志并重试。在5次失败尝试(默认)后,它将中止并出现SCN未找到错误。
如何排查
首先查看INFO级别的日志,Debezium在那里报告哪些线程或序列不一致。如果您没有看到这些,请增加以下类的日志记录:
io.debezium.connector.oracle.logminer.LogFileCollector 如果您的数据库负载过重或日志更改频繁,默认的重试策略可能不足。您可以使用以下设置调整重试行为:
{
"internal.log.mining.log.query.max.retries": "10",
"internal.log.mining.log.backoff.initial.delay.ms": "1000",
"internal.log.mining.log.backoff.max.delay.ms": "60000"
} 这些选项实现了指数退避:1秒、2秒、4秒……,直到日志变得一致,或达到最大重试次数。
总结
“在线重做日志文件或归档日志文件不包含偏移量SCN”这个错误可能令人沮丧,但它通常是更深层的日志可用性或协调问题的症状。通过理解:
-
SCN与重做日志和LogMiner的关系
-
在线日志与归档日志的区别
-
Debezium的内部一致性检查
您可以更有效地诊断和预防这些问题。
如有疑问,请检查:
-
启动时的偏移量SCN有效性
-
日志保留和线程覆盖
-
挖掘时的重做线程一致性
-
心跳配置,以避免空闲流中的陈旧数据。
通过正确的监控和配置,这些错误可以成为罕见的事件,而不是反复出现的障碍。
关于 Debezium
Debezium 是一个开源的分布式平台,可以将现有数据库转变为事件流,使应用程序能够几乎即时地看到并响应数据库中已提交的每个行级更改。Debezium 构建在 Kafka 之上,并提供了 Kafka Connect 兼容的连接器,用于监控特定的数据库管理系统。Debezium 将数据更改的历史记录在 Kafka 日志中,这样您的应用程序可以随时停止和重新启动,并可以轻松地消费在未运行时错过的所有事件,确保所有事件都被正确且完整地处理。Debezium 在 Apache 许可证 2.0 下是 开源 的。