SQL Транзакция перекрывается между C# и T- SQL - PullRequest
1 голос
/ 13 февраля 2020

У меня есть C# процесс, который вставляет записи в таблицу внутри транзакции. В течение этого времени другой процесс (хранимая процедура SQL) обновляет эту таблицу. Процесс C# использует сериализуемый режим изоляции, а SP использует фиксацию чтения.

В обновляемой таблице есть поле даты и времени с именем DateShipped, которое процесс C# вставляет с использованием текущего времени. Процессу C# требуется около 1 с, чтобы определить значения и использовать оператор вставки. Изучив данные в таблице, вы увидите, что все записи, добавленные в транзакцию, имеют разницу в 1 с в поле DateShipped. Давайте не будем беспокоиться о том, как сделать этот процесс лучше. В настоящее время меня интересует, как SP может обновить запись, которая находится в транзакции другого процесса и не была зафиксирована.

В таблице есть еще одно поле TransID, определенное как INT. Процесс C# не указывает значение для этого поля при вставке, поэтому по умолчанию используется значение NULL. SP запускается по расписанию, и первым делом он обновляет все записи, в которых TransID IS NULL, до указанного значения. SP запускается в рамках явной транзакции.

Бывают случаи (не уверен, что это всегда так, как я не знаю, как часто они оба запускаются в одно и то же время), когда некоторые из записей (первая так много) обновляются с помощью TransID, когда другие в той же транзакции этого не делают.

Как получается, что SP может видеть первые столько записей, но не все из них?

Есть ли способ использовать расширенные события, чтобы захватить это?

Вставить результаты:

Insert Results

DateShipped             TransID
2020-02-12 00:26:47.680 514928
2020-02-12 00:26:49.090 514929
2020-02-12 00:26:50.057 514929
2020-02-12 00:26:51.027 514929
2020-02-12 00:26:51.963 514929
2020-02-12 00:26:52.887 514929
2020-02-12 00:26:53.807 514929
2020-02-12 00:26:54.747 514929
2020-02-12 00:26:55.713 514929
2020-02-12 00:26:56.700 514929
2020-02-12 00:26:57.700 514929
2020-02-12 00:26:58.653 514929
2020-02-12 00:26:59.620 514929
2020-02-12 00:27:00.573 514929

Может кто-нибудь порекомендовать способ предотвратить это (обновление незафиксированная вставка из другой транзакции) или захватить относительную информацию, чтобы показать, что это происходит?

Дополнительная информация

Код процесса 1 (c#)

ADODB.Connection.BeginTrans()

... Several inline SELECTs and INSERTs via ADODB.Connection.Execute()

ADODB.Connection.CommitTrans()

Вставка устанавливает в поле DateShipped текущую дату / время. Поэтому DateShipped - это дата / время вставки.

Код процесса 2 (хранимая процедура)

BEGIN TRANSACTION

SELECT @ID = (MAX(TransID) + 1) FROM dbo.tHostInterfaceExport
INSERT INTO dbo.tHostInterfaceExport ( TransID ) VALUES (@ID)

EXEC dbo.dloc_UpdateActivityTables @ID

COMMIT TRANSACTION

PROCEDURE dbo.dloc_UpdateActivityTables @TransID INT

UPDATE dbo.tActivityShipments
SET TransID = @TransID
WHERE TransID IS NULL

Проблема заключается в том, что этот оператор UPDATE иногда (возможно, только когда два процесса выполняются одновременно) обновляет только некоторые из первых записей, вставленных в процесс 1.

Вот еще один пример данных, в которых возникла проблема. Все эти записи были записаны в рамках одной транзакции процесса 1.

DateShipped             TransID
2020-02-12 10:54:29.157 244878
2020-02-12 10:54:30.063 244878
2020-02-12 10:54:30.940 244878
...
2020-02-12 10:56:31.290 244878
2020-02-12 10:56:31.867 244878
2020-02-12 10:56:32.493 244878  <-- why was this one and the above ones updated
2020-02-12 10:56:33.087 244879  <-- and not this one and the ones below?
2020-02-12 10:56:33.730 244879
2020-02-12 10:56:34.353 244879
...
2020-02-12 10:57:32.360 244879
2020-02-12 10:57:33.093 244879
2020-02-12 10:57:33.970 244879

Дополнительная информация о том, когда был создан TransID. TransID создается в начале процесса 2. Это показывает, что процесс 2 вызывался 2 раза и 3 минуты друг от друга.

TransID DateCreated
244878  2020-02-12 10:54:56.817
244879  2020-02-12 10:57:56.880

Интересно, что процесс 2 планируется запускать каждые 60 с, все же он был задержан (ожидая, пока процесс 1 завершит sh и зафиксирует транзакцию) перед завершением TransID 244878. Я говорю это потому, что запись для TransID = 244879 должна была произойти в 10:55:56 или 10:56:56 , но процесс все еще ждал предыдущего обновления, которое было заблокировано транзакцией вставки, которая завершилась после последней вставки в 10: 57: 33.970.

1 Ответ

0 голосов
/ 19 февраля 2020

Проблема оказалась COMMIT в процессе 1, который преждевременно завершал транзакцию.

Процесс 1 запускал транзакцию, а затем выполнял кучу работы. Частью работы был вызов хранимой процедуры, у которой был COMMIT. Как только это было выполнено, транзакция была завершена, и процесс 2. смог продолжить.

Мне все еще нужно понять, почему процесс 1 не выдал ошибку, когда он выполнил предполагаемую транзакцию фиксации.

Спасибо Петру за предложение использовать триггер для получения дополнительной информации.

...