SQL deadlock question

Is it possible for relational databases to stumble on these two statements? I am trying to simplify my question and example - just assume that for these samples, which, it seems to me, usually only requires a joint read lock, exclusive read locks are now required:

Concurrent Connection 1: SELECT {...} FROM A JOIN B ON {...} Concurrent Connection 2: SELECT {...} FROM B JOIN A ON {...} 

That is, does ordering of associations make sense? Are individual statements in SQL atomic? Is the first and then B locked in the first statement, and B locked first, and then A in the second expression?

I think not. “My gut tells me that two separate statements like this can't slow down, no matter how complicated they are.” I believe that the assertion is parsed as a whole and that resources requiring locking are blocked using some deterministic global order (i.e., in alphabetical order). But I need more than a gut feeling for it - I can't think of a way to prove it, and I can't find it documented.

I'm interested in MS SQL 2005, but I don’t think the question is implementation specific.

Secondarily: as far as MS SQL is concerned, I would also like to know that Common Table Expressions also have this guarantee - CTEs basically represent a syntactic advantage (+ recursion), combined into a traditional single instruction for the engine.

+4
source share
3 answers

SELECTs cannot block other SELECTs because they only get general locks. You say that we must take into account that these SELECTs now require exclusive read locks, but this is impossible for us because 1) there are no such things as exlusive read lock and 2) reads do not acquire exclusive locks.

But you pose a more general question, whether simple statements can be blocked. The answer is a definite, loud YES . Locks are acquired at execution, are not analyzed in advance and sorted, and then purchased in a specific order. It would be impossible for the engine to know the necessary locks in advance, because they depend on the actual data on the disk and for reading the data that the engine needs to lock the data.

Dead ends between simple statements (SELECt versus UPDATE or SELECT or DELETE) due to the different order of access to the index are quite common and very easy to examine, diagnose and correct. But note that there is always a write operation, since reads cannot block each other. For this discussion, the addition of an UPDLOCK or XLOCK hint of SELECT should be considered a record. You don’t even need a JOIN, the secondary index may well introduce an access order problem leading to a deadlock, see Reading / Writing a Deadlock .

Finally, the SELECT FROM A JOIN B record or the SELECT FROM B JOIN A record is completely irrelevant. The query optimizer is free to change the access order at its discretion, the actual text of the request does not impose the execution order in any way.

Update

How then can we build a general strategy regarding the READING COMMITTEE database "multiple entity", which is not inhibited?

I am afraid that the cookie cutter recipe does not exist. The decision will depend on case by case. Ultimately, in database applications, deadlocks are a fact of life. I understand that this may seem absurd, because "we landed on the moon, but we cannot write the right database application," but there are strong factors in the game that pretty much guarantee that applications will end up with deadlocks. Successful deadlocks are the easiest way to handle errors, just read the state, apply logic, rewrite the new state. Now that they say, there are some good practices that can significantly reduce the frequency of deadlocks, to the point that they have almost disappeared:

  • Try creating a consistent access pattern for Writes. Well-defined rules that specify things like “transaction, should always have tables in the following order: CustomersOrderHeadersOrderLines . 'Note that the order must be executed within the transaction. Basically, classify all the tables in your schema and specify that all updates must be performed in order of ranking, which ultimately boils down to the code discipline of the individual contributor writing the code, as he must ensure that he writes, updates the sin in the proper order within the transaction.
  • Reduce the recording time. The usual wisdom is this: at the beginning of the transaction, do all the readings (read the existing state), then process the logic and calculate new values, and then write down all the updates at the end of the transaction. Avoid patterns like "read-> write-> logic-> read-> write", instead of "read-> read-> logic-> write-> write". Of course, true mastery is how to deal with real, real, individual cases, when, apparently, you need to make notes in the middle of a transaction. A special note here should be said about the specific type of transaction: those that are controlled by the queue, which by the very definition begin their activity by dequeueing (= a write) from the queue. These applications have always been sadly printed and prone to errors (especially dead ends); fortunately, there are ways to do this, see Using Tables as Queues .
  • Reduce the number of readings. Table scans are the most common cause of deadlocks. Proper indexing will not only eliminate deadlocks, but can also improve process performance.
  • Snapshot isolation . This is the closest thing you get for a free lunch to avoid dead ends. I intentionally set it last because it can mask other problems (for example, incorrect indexing) instead of fixing them.

Trying to solve this problem with the LockCustomerByXXX approach, I'm afraid it does not work. Pessimistic blocking does not scale. Optimistic concurrency updates are the way to go if you want decent performance.

+9
source

As far as I know, you're right: the SQL engine calculates what it will need to do (possibly when it parses the query), blocks all the necessary resources, executes the query, and then unlocks them.

0
source

Reading will not block each other. You must also write.

You can do everything to reduce deadlocks. For example, insert only the end of the clustered index on platforms that support row locking and avoid updating records. Ah hah, now the Facebook user interface makes more sense.

Sometimes it’s easier to deal with dead ends than to avoid them. The server will fail and report, and you can try again.

0
source

Source: https://habr.com/ru/post/1315826/


All Articles