Рассмотрим базу данных SQL Server и два ее хранимых процесса:
* 1. Proc, который выполняет 3 важные вещи в транзакции: создать клиента, вызвать sproc, чтобы выполнить другую вставку, и условно вставить третью запись с новым идентификатором.
BEGIN TRAN
INSERT INTO Customer(CustName) (@CustomerName)
SELECT @NewID = SCOPE_IDENTITY()
EXEC CreateNewCustomerAccount @NewID, @CustomerPhoneNumber
IF @InvoiceTotal > 100000
INSERT INTO PreferredCust(InvoiceTotal, CustID) VALUES (@InvoiceTotal, @NewID)
COMMIT TRAN
* 2. Хранимый процесс, который опрашивает таблицу Customer
на предмет новых записей, которые не имеют связанную запись PreferredCust
. Клиентское приложение выполняет опрос, вызывая этот сохраненный процесс каждые 500 мс. SELECT на Customer
НЕ включает транзакцию.
--not in the Preferred list
SELECT C.ID
FROM Customer AS C
LEFT JOIN PreferredCust AS PRE ON PRE.CustID = C.ID
WHERE PRE.CustID IS NULL
Возникла проблема, когда хранимая процедура опроса нашла запись в таблице Customer
и вернула ее как часть своих результатов. Проблема была в том, что он взял эту запись, я полагаю, как часть грязного чтения. Запись в конечном итоге имела запись в PreferredCust
позже, и в результате возникла проблема ниже по течению.
Вопрос
- Как вы можете явно предотвратить грязное чтение этим вторым сохраненным процессом?
- Насколько вероятно мое предположение о сценарии грязного чтения?
Средой является SQL Server 2005 со стандартной конфигурацией по умолчанию. Никаких других блокировочных ударов в этих хранимых процедурах не дано.
Эти два хранимых процесса вызываются из клиента Java через соединение JDBC. Неизвестно, используют ли они одно и то же соединение, но SQL Profiler показывает, что они используют тот же SPID и ClientProcessID .
Вот что показывает SQL Profiler:
SELECT @@MAX_PRECISION
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SET IMPLICIT_TRANSACTIONS OFF
SET QUOTED_IDENTIFIER ON
SET TEXTSIZE 2147483647
go
EXEC WriteNewCustomer 'CustomerX', 199000
go
--get any customers in the priority
SELECT @@MAX_PRECISION
SET TRANSACTION ISOLATION LEVEL READ COMMITTED
SET IMPLICIT_TRANSACTIONS OFF
SET QUOTED_IDENTIFIER ON
SET TEXTSIZE 2147483647
go
EXEC GetCustomersWithLowInvoice
go