【发布时间】:2010-04-26 23:25:21
【问题描述】:
考虑一个 SQL Server 数据库及其两个存储过程:
*1。一个在事务中执行 3 件重要事情的 proc:创建一个客户,调用一个 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 毫秒调用一次此存储过程来执行轮询。 Customer 上的 SELECT 不涉及事务。
--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,默认配置为开箱即用。在这些存储过程中都没有给出其他锁定命中。
这两个存储过程是通过 JDBC 连接从 Java 客户端调用的。不知道它们是否使用相同的连接,但 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
【问题讨论】:
标签: sql-server sql-server-2005 tsql