首页 > 解决方案 > 在 JDBC 驱动程序上并行执行 MERGE 命令不起作用

问题描述

我在同一个 JDBC 连接上并行运行 ~22 个 MERGE 命令。在所有并行执行完成后,我正在提交事务。我已打开显式事务。以下是我正在使用的 MERGE 命令:

MERGE INTO _1 AS A USING ( select $1:Id::VARCHAR as Id,  $1:modifiedUtc::NUMBER as MODIFIEDUTC,  $1:VersionId::NUMBER as VersionId,  $1 as DATA FROM '@EXTERNAL_AWS_STAGE/group1/' (FILE_FORMAT => JSON_FORMAT) ) AS B  ON A.Id = B.Id  WHEN MATCHED AND A.VersionId < B.VersionId  THEN UPDATE SET A.VersionId = B.VersionId, A.MODIFIEDUTC = B.MODIFIEDUTC, A.DATA = B.DATA  WHEN NOT MATCHED  THEN INSERT (Id, MODIFIEDUTC, VersionId, DATA) VALUES (B.Id, B.MODIFIEDUTC, B.VersionId, B.DATA);

MERGE INTO _2 AS A USING ( select $1:Id::VARCHAR as Id, $1:modifiedUtc::NUMBER as MODIFIEDUTC, $1:VersionId::NUMBER as VersionId, $1 as DATA FROM '@EXTERNAL_AWS_STAGE/group2/' (FILE_FORMAT => JSON_FORMAT) ) AS B ON A.Id = B.Id WHEN MATCHED AND A.VersionId < B.VersionId THEN UPDATE SET A.VersionId = B.VersionId, A.MODIFIEDUTC = B.MODIFIEDUTC, A.DATA = B.DATA WHEN NOT MATCHED THEN INSERT (Id, MODIFIEDUTC, VersionId, DATA) VALUES (B.Id, B.MODIFIEDUTC, B.VersionId, B.DATA);

对于三个相同的表,问题是一些表没有得到更新,而另一些表则在更新。并不是某个特定的表没有得到更新。有时,说表 _1 正在更新,有时没有。我验证了 executeUpdate(query) 方法为所有 MERGE 命令返回 1,表示为所有表更新或插入一行,但 select * from _1 为其中一些返回 0 行。代码库要么提交要么回滚事务,最后关闭连接。

当我尝试通过 Snowflake Worksheets 运行相同的 MERGE 命令时,我可以看到所有表中的数据都已更新。

任何指针都会非常有帮助。

一些重要的观察:

  1. 由于我们必须在事务边界内处理更新,因此我们调用 Connection.setAutoCommit(false)。如果未启用,则不会观察到上述问题。
  2. 我们以 20 个批次向 Snowflake 发送查询以供执行。使用相同的数据库连接同时触发所有 20 个查询。每批 20 个 MERGE 命令后都会有 2 秒的暂停。
  3. 如果我们尝试按顺序执行 MERGE 命令,则不会观察到问题。即使在表上进行了几次活动锁定之后,提交也会成功并且表中的数据也会更新。
  4. 对于空的数据表,即使 Snowflake History 也表示 MERGE 命令成功完成,每个 MERGE 命令的行数为 1。
  5. SHOW TRANSACTIONS 命令仅在事务处于活动状态之前显示活动事务。成功提交后,此命令不会显示任何活动事务。
  6. SHOW LOCKS 命令显示可变数量的锁,范围从 1 到超过所涉及的表的数量。
  7. 如果我们检查 SHOW LOCKS 命令的结果集中返回的查询 id 的历史记录,我们发现查询已经成功完成。

请提供任何可能有助于进一步确定问题的指示。

标签: snowflake-cloud-data-platform

解决方案


您是否使用最新的 Snowflake JDBC 连接器并按照以下方式明确设置多语句选项? https://docs.snowflake.net/manuals/user-guide/jdbc-using.html#multi-statement-jdbc


推荐阅读