05.11.2015 Views

Apress.Expert.Oracle.Database.Architecture.9i.and.10g.Programming.Techniques.and.Solutions.Sep.2005

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

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

CHAPTER 6 ■ LOCKING AND LATCHING 193<br />

So, if the application code itself is not to be made responsible for maintaining this LAST_MOD<br />

field, then I believe that the application should not be made responsible for checking this<br />

LAST_MOD field either (if it can do the check, it can certainly do the update!). So, in this case, I<br />

suggest encapsulating the update logic in a stored procedure <strong>and</strong> not allowing the application<br />

to update the table directly at all. If it cannot be trusted to maintain the value in this field, then<br />

it cannot be trusted to check it properly either. So, the stored procedure would take as inputs<br />

the bind variables we used in the previous updates <strong>and</strong> do exactly the same update. Upon<br />

detecting that zero rows were updated, the stored procedure could raise an exception back to<br />

the client to let the client know the update had, in effect, failed.<br />

An alternate implementation uses a trigger to maintain this LAST_MOD field, but for something<br />

as simple as this, my recommendation is to avoid the trigger <strong>and</strong> let the DML take care<br />

of it. Triggers introduce a measurable amount of overhead, <strong>and</strong> in this case they would be<br />

unnecessary.<br />

Optimistic Locking Using a Checksum<br />

This is very similar to the previous version column method, but it uses the base data itself to<br />

compute a “virtual” version column. I’ll quote the <strong>Oracle</strong> 10g PL/SQL Supplied Packages Guide<br />

(before showing how to use one of the supplied packages!) to help explain the goal <strong>and</strong> concepts<br />

behind a checksum or hash function:<br />

A one-way hash function takes a variable-length input string, the data, <strong>and</strong> converts it<br />

to a fixed-length (generally smaller) output string called a hash value. The hash value<br />

serves as a unique identifier (like a fingerprint) of the input data. You can use the hash<br />

value to verify whether data has been changed or not.<br />

Note that a one-way hash function is a hash function that works in one direction. It is<br />

easy to compute a hash value from the input data, but it is hard to generate data that<br />

hashes to a particular value.<br />

The hash value or checksum is not truly unique. It is just designed such that the probability<br />

of a collision is sufficiently small—that is, the probability of two r<strong>and</strong>om strings having the<br />

same checksum or hash is so small as to be negligible.<br />

We can use these hashes or checksums in the same way that we used our version column.<br />

We simply compare the hash or checksum value we obtain when we read data out of the database<br />

with what we obtain before modifying the data. If someone modified the row’s values<br />

after we read it out, but before we updated it, then the hash or checksum will almost certainly<br />

be different.<br />

There are many ways to compute a hash or checksum. I’ll list three of these <strong>and</strong> demonstrate<br />

one in this section. All of these methods are based on supplied database packages:<br />

• OWA_OPT_LOCK.CHECKSUM: This method is available on <strong>Oracle</strong>8i version 8.1.5 <strong>and</strong> up.<br />

There is a function that given a string returns a 16-bit checksum, <strong>and</strong> another function<br />

that given a ROWID will compute the 16-bit checksum of that row <strong>and</strong> lock that row at<br />

the same time. Possibilities of collision are 1 in 65,536 strings (the highest chance of a<br />

false positive).

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

Saved successfully!

Ooh no, something went wrong!