17.06.2013 Views

Beginning Microsoft SQL Server 2008 ... - S3 Tech Training

Beginning Microsoft SQL Server 2008 ... - S3 Tech Training

Beginning Microsoft SQL Server 2008 ... - S3 Tech Training

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Chapter 14: Transactions and Locks<br />

indeed be set to –25, even though it logically appeared that we prevented this through the use of our IF<br />

statement.<br />

We can prevent this problem in only two ways:<br />

❑ Create a CHECK constraint and monitor for the 547 Error.<br />

❑ Set our isolation level to be REPEATABLE READ or SERIALIZABLE.<br />

The CHECK constraint seems fairly obvious. The thing to realize here is that you are taking something of<br />

a reactive rather than a proactive approach with this method. Nonetheless, in most situations we have a<br />

potential for non-repeatable reads, so this would be my preferred choice in most circumstances.<br />

We’ll be taking a full look at isolation levels shortly, but for now, suffice it to say that there’s a good chance<br />

that setting it to REPEATABLE READ or SERIALIZABLE is going to cause you as many headaches as it<br />

solves (or more). Still, it’s an option.<br />

Phantoms<br />

436<br />

No, we’re not talking the of the Opera kind here — what we’re talking about are records that appear mysteriously,<br />

as if unaffected by an UPDATE or DELETE statement that you’ve issued. This can happen quite<br />

legitimately in the normal course of operating your system and doesn’t require any kind of elaborate<br />

scenario to illustrate. Here’s a classic example of how this happens.<br />

Let’s say you are running a fast food restaurant. If you’re running a typical establishment of that kind,<br />

you probably have a fair number of employees working at the minimum wage as defined by the government.<br />

The government has just decided to raise the minimum wage from $6.50 to $7.50 per hour, and you<br />

want to run an UPDATE on the EmployeePayHistory table to move anyone making less than $7.50 per<br />

hour up to the new minimum wage. “No problem,” you say, and you issue the rather simple statement:<br />

UPDATE HumanResources.EmployeePayHistory<br />

SET HourlyRate = 7.50<br />

WHERE HourlyRate < 7.50;<br />

ALTER TABLE Employees<br />

ADD ckWage CHECK (HourlyRate >= CONSTRAINT 7.50);<br />

GO<br />

That was a breeze, right? Wrong! Just for illustration, we’re going to say that you get an error message back:<br />

Msg 547, Level 16, State 1, Line 1<br />

ALTER TABLE statement conflicted with COLUMN CHECK constraint ‘ckWage’. The<br />

conflict occurred in database ‘AdventureWorks<strong>2008</strong>’, table ‘EmployeePayHistory’,<br />

column ‘Rate’.<br />

So you run a quick SELECT statement checking for values below $7.50, and sure enough you find one.<br />

The question is likely to come rather quickly, “How did that get there? I just did the UPDATE that should<br />

have fixed that!” You did run the statement, and it ran just fine — you just got a phantom.<br />

The instances of phantom reads are rare and require just the right circumstances to happen. In short,<br />

someone performed an INSERT statement at the very same time your UPDATE was running. Since it was<br />

an entirely new row, it didn’t have a lock on it and it proceeded just fine.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!