首页 > 解决方案 > 为什么一个 Java 线程只能取回 SQLServer 中另一个线程插入的数据的一半?

问题描述

在这种特定情况下,我有两个线程:

  1. 一种是轮询磁盘上特定文件夹中的新文件。它使用文件中的元数据将作业插入数据库(跨多个表)。Autocommit 设置为 false,我只在循环结束时提交(假设一次找到多个文件,每个文件提交一次)。
  2. 另一个线程不断地轮询要处理的新“作业”。它主要查询一个表,但有几个左连接。该查询with (updlock, readpast)仅在主表上使用表提示。

我注意到一些返回的作业缺少一个或多个左连接的值,但只是第一次(它导致失败,然后触发该作业在几秒钟后再次被拾取)。我确定该值实际上不是 null,因为我在每个插入数据的查询之前和之后添加了日志语句。我已确保禁用自动提交,并且只有在所有数据都存在时才提交。

不过,我注意到的一件事似乎是一种模式,即轮询线程在另一个线程完成之前不久就开始了它的查询。它可能是一两个操作落后,或者它可能即将提交。它在第一个线程提交后返回结果(基于我日志中的时间戳)。

我不明白这怎么会发生。我readpast对主表有一个提示,所以它甚至不应该在查询中返回。但它返回时没有来自连接表的关联数据,它没有任何提示。如果运行需要几秒钟(虽然它通常很快),理论上它应该遇到尚未提交的锁定行,然后跳过它。

这是我用来轮询新工作的查询的一个简单示例。

SELECT distinct
  j.id,
  p.request_path,
  j.revision_id,
  j.status,
  j.creation_date,
  dr.dependent_revision_id
from incoming_jobs j WITH (updlock, readpast)
  left join file_paths p on j.revision_id = p.revision_id
  left join dependent_revisions dr on j.id = dr.job_id
where j.status in ('WAITING')
  and dr.dependent_revision_id is null
order by j.creation_date offset 0 rows fetch next 3 row only

在这种情况下,作业中有一个非空值file_paths,但无论如何它都会返回空值。incoming_jobs该值在另一个线程将作业插入表后立即插入。

标签: sql-servermultithreadingjdbc

解决方案


推荐阅读