如果将数据库中的主键字段自动递增为递增字段,kafka-connect-jdbc在丢失和重复行方面是否安全?
答案 0 :(得分:1)
我为此目的进行了分析,并得出结论,使用"递增"带有PK列的模式,除非您正在处理非事务性数据库。这是因为自动递增的PK的序列号在事务期间(执行INSERT时)被分配,但行仅在事务提交时出现,因此它们可能出现乱序。想象一下不那么罕见的情景:
为了克服这样的错过行,你可以考虑在你的jdbc驱动程序配置中使用DIRTY READ,但是你会看到可能参与后来回滚但不应该被读取的事务的插入。
而不是"递增"我建议你考虑"时间戳"或者"时间戳+递增"模式。 https://docs.confluent.io/current/connect/connect-jdbc/docs/source_config_options.html#mode 并设置" timestamp.delay.interval.ms"适当地配置为不按顺序完成的长时间运行的事务的容差。我无法从经验中说出,如果100%安全,因为我必须处理的数据库不符合ANSI SQL,并且kafka-connect-jdbc的时间戳相关功能不会出现这种情况。工作。
答案 1 :(得分:0)
在自动递增模式下绝对不安全。问题是事务隔离和由此产生的可见性特征-事务开始的顺序(以及它们可能获取的任何自动递增字段的值)与这些事务提交的顺序不同。在混合工作负载中,此问题尤其明显,在这种情况下,事务可能需要花费不同的时间才能完成。因此,作为观察员,您将在表中看到的是可见记录中的临时“空白”,直到这些事务完成为止。如果键0的事务T0
在键T1
的{{1}}之前开始,但1
首先完成,则Kafka Connect源连接器将观察T1
的影响,发布记录,并将水印前进到键T1
。稍后,1
最终将提交,但是到那时,源连接器将继续前进。
这是reported issue,并且Kafka Connect文档对已知限制并不透明(尽管自2016年以来KC JDBC团队一直在讨论该问题)。
一种解决方法是使用时间戳记模式(这本身并不安全),并通过T0
属性添加延迟。按照Confluent documentation:
出现具有特定时间戳记的行之后需要等待多长时间,然后才将其包括在结果中。您可以选择添加一些延迟,以允许时间戳较早的事务完成。第一次执行将获取所有可用记录(即从时间戳0开始),直到当前时间减去延迟为止。接下来的每次执行都会从上一次获取数据到当前时间减去延迟。
这(尴尬地)解决了一个问题,但引入了另一个问题。现在,在发生时间戳延迟的持续时间内,源宿将滞后于表的“尾部”(可以说),这是在潜在宽限期内提交潜在事务的机会。宽限期越长,滞后时间就越长。因此,在需要近实时消息传递的应用程序中,这可能不是一个选择。
您可以尝试放宽源接收器查询的隔离级别,但这还有其他含义,特别是如果您的应用程序依靠transaction outbox pattern来保证消息传递。
Kafka Connect的一个 safe 解决方案是采用CDC(更改数据捕获)或等效方法,并将源接收器指向CDC表(按提交顺序)。您可以使用原始CDC或Debezium作为“便携式”变体。这将添加到数据库I / O,但为连接器提供了线性历史记录以供处理。