В этом конкретном сценарии c у меня есть два потока:
- Один из них - опрос новых файлов на диске в указанной c папке. Он использует метаданные из файла для вставки заданий в базу данных (по нескольким таблицам). Autocommit имеет значение false, и я фиксирую только в конце l oop (при условии, что одновременно найдено более одного файла, он фиксирует один раз на файл).
- Другой поток постоянно опрос новых рабочих мест для обработки. Он запрашивает в основном одну таблицу, но есть несколько левых соединений. Запрос использует табличные подсказки
with (updlock, readpast)
только для первичной таблицы.
Я заметил, что в некоторых возвращаемых заданиях отсутствуют значения для одного или нескольких левых объединений, но только для в первый раз (это приводит к сбою, который затем запускает эту работу снова через несколько секунд). Я точно знаю, что значение на самом деле не равно нулю, потому что я добавил записи журнала до и после каждого запроса, который вставляет данные. Я удостоверился, что автокоммит отключен, и я фиксирую только после того, как все фрагменты данных есть.
Одна вещь, которую я заметил, хотя, которая, кажется, является шаблоном, - то, что поток опроса вскоре начинает свой запрос до того, как закончится другой поток. Это может быть одна или две операции позади, или это может быть только для фиксации. Это возвращает результат после того, как первый поток фиксирует (основанный на отметках времени в моем журнале).
Я не понимаю, как это могло произойти. У меня есть подсказка 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
другим потоком.