Database Reference
In-Depth Information
transaction. If the outcome of the decision is dependent on the data read by the SELECT statement, then you should
consider preventing modification of the data by other concurrent transactions. For example, consider the following
two transactions:
Normalize the price for ProductID = 1 : For ProductID = 1 , if Price > 10 , then decrease the
price by 10 .
Apply a discount : For products with Price > 10 , apply a discount of 40 percent .
Now consider the following test table:
IF (SELECT OBJECT_ID('dbo.MyProduct')
) IS NOT NULL
DROP TABLE dbo.MyProduct ;
GO
CREATE TABLE dbo.MyProduct
(ProductID INT,
Price MONEY
) ;
INSERT INTO dbo.MyProduct
VALUES (1, 15.0) ;
You can write the two transactions like this:
DECLARE @Price INT ;
BEGIN TRAN NormailizePrice
SELECT @Price = mp.Price
FROM dbo.MyProduct AS mp
WHERE mp.ProductID = 1 ;
/*Allow transaction 2 to execute*/
WAITFOR DELAY '00:00:10' ;
IF @Price > 10
UPDATE dbo.MyProduct
SET Price = Price - 10
WHERE ProductID = 1 ;
COMMIT
--Transaction 2 from Connection 2
BEGIN TRAN ApplyDiscount
UPDATE dbo.MyProduct
SET Price = Price * 0.6 --Discount = 40%
WHERE Price > 10 ;
COMMIT
On the surface, the preceding transactions may look good, and yes, they do work in a single-user environment.
But in a multiuser environment, where multiple transactions can be executed concurrently, you have a problem here!
To figure out the problem, let's execute the two transactions from different connections in the following order:
1.
Start transaction 1 first.
2. Start transaction 2 within ten seconds of the start of transaction 1.
As you may have guessed, at the end of the transactions, the new price of the product (with ProductID = 1 ) will
be -1.0 . Ouch—it appears that you're ready to go out of business!
Search WWH ::




Custom Search