I have a complex select query and a huge table.
I'm running this select
statement, meanwhile an Update
statement arrives and tries to update the table.
IMHO - update requires an exclusive lock - so the update statement will have to wait till the select command is finished.
Am I right ?
what can I do in order to: execute the complex select
, and also let the update
command run (currently I don't care about dirty data)
Think of it this way -- It locks every row it had to look at. No index on the column -- It had to check every row, so all rows are locked. That effectively locks the entire table. UNIQUE index on the column -- Only one row need be touched, hence, locked.
SELECT statements get a shared lock on the entire table. Other statements get exclusive locks on the entire table, which are released when the transaction commits. SELECT statements get shared locks on a range of rows. UPDATE and DELETE statements get exclusive locks on a range of rows.
Yes it does take a shared lock on the rows that it reads by default (it also takes an Intent Shared lock on all the pages of the clustered index that it will read), this is done to prevent dirty reads.
An UPDATE lock is a read lock which means "I intend to update this row/page/table". Readers are not blocked by this lock, but only one process can hold an UPDATE lock on a resource. please simulate a scenario which show where update lock play a key role because we know sql server place a lock when update data.
Yes - to a degree.
How long a SELECT
holds on to a shared lock is depending on the isolation level of the transaction:
READ UNCOMMITTED
- no shared lock is acquired at all - UPDATE
is not blockedREAD COMMITTED
- shared lock is acquired just for the duration of reading the data - UPDATE
might be blocked for a very short period of timeREPEATABLE READ
and SERIALIZABLE
- shared lock is acquired and held on to until the end of the transaction - UPDATE
is blocked until the SELECT
transaction endsTechnically, the UPDATE
statement first gets an UPDATE
lock - which is compatible with a shared lock (as used by the SELECT
) - for the duration of the time while it's reading the current values of the rows to be updated.
Once that's done, the Update
lock is escalated to an exclusive lock for the new data to be written to the table.
When you run the two statements concurrently (a SELECT and an UPDATE) the actual behavior will be basically random. This is because neither of the operations is instantaneous. To simplify, consider your table a list and SELECT is traversing this list, looking at one row at a time. UPDATE is also trying to update one or more rows. When the UPDATE is trying to update a row behind the SELECT then nothing happens (no blocking) because the SELECT has already progressed past the UPDATE point. If the UPDATE is trying to update the row at which SELECT is looking right now then the UPDATE will have to wait for SELECT to move on, which will happen very very very fast and the UPDATE will unblock and succeed, while the SELECT is moving ahead. But if the UPDATE is updating a row ahead of the SELECT then the update will succeed and, later, SELECT will eventually reach exactly this row and will stop, blocked. Now SELECT has to wait until the transaction that did the UPDATE commits.
This is the simplified story. The real life is much more complicated. The SELECT can have multiple read points (parallel plans). Both the SELECT and the UPDATE are subject to choosing an access path, meaning use one or more secondary indexes to locate the rows. Complex queries may contain operators that cause multiple lookups into a table (eg. joins). Both the SELECT and the UPDATE can do bookmark lookups to fetch BLOB data, which changes significantly the locking behavior. Cardinality estimation may cause the SELECT to run at a high granularity lock mode (eg. table level Shared lock). The UPDATE can trigger lock escalation, and the escalation can fail or succeed. Choosing different access paths can lead to deadlock. False lock contention can occur due to hash collisions. There are just about one myriad variables that have a say in this. And I didn't even mention higher isolation levels (repeatable read, serializable).
Perhaps you should use SNAPSHOT isolation and stop worrying about this issue?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With