sqlsql-servert-sqltransactionssnapshot-isolation

With TSQL SNAPSHOT ISOLATION, is it possible to update only non-locked rows?


A large SQL Server 2008 table is normally being updated in (relatively) small chunks using a SNAPSHOT ISOLATION transaction. Snapshot works very well for those updates since the chunks never overlap. These updates aren't a single long running operation, but many small one-row insert/update grouped by the transaction.

I would like a lower priority transaction to update all the rows which aren't currently locked. Does anyone know how I can get this behavior? Will another SNAPSHOT ISOLATION transaction fail as soon as it a row clashes, or will it update everything it can before failing?

Could SET DEADLOCK_PRIORITY LOW with a try-catch be of any help? Maybe in a retry loop with a WHERE which targets only rows which haven't been updated?


Solution

  • Snapshot isolation doesn't really work that way; the optimistic locking model means it won't check for locks or conflicts until it's ready to write/commit. You also can't set query 'priority' per se, nor can you use the READPAST hint on an update.

    Each update is an implicit atomic transaction so if 1 update out of 10 fails (in a single transaction) they all roll back.

    SET DEADLOCK_PRIORITY only sets a preference for which transaction is rolled back in the event of a dealdlock (otherwise the 'cheapest' rollback is selected).

    A try-catch is pretty much a requirement if you're expecting regular collisions.

    The retry loop would work as would using a different locking model and the NOWAIT hint to skip queries that would be blocked.