DeadlockingDemos Explanations and hints

advertisement
Setup
The database and tables for all demos can be set up most simply by executing the
SetupDeadlockDemos.bat batch.
Alternatively, you can run the setup scripts individually on Demo2 – Demo6. But the deadlock demos
will only work if the tables from the setups exist, and the demos are run from the demo batch files in
each directory.
On each of the demos, use the methods you would normally use to detect and resolve deadlocks. This
includes tracing and capturing the deadlock graph, lock escalation, etc. and using the 1204 and 1222
trace flags. The trace flags especially may be helpful in disambiguating some of the possible deadlock
graphs you may see in Demo3.
All of the deadlock demos except Demo3 should work on single processor machines. Demo3 must
have a multi-processor machine to deadlock.
Note that most of these demos involve shared locks, so the database must not be using READ
COMMITTED SNAPSHOT at the time the demos are run. As a demo of another way to resolve the
deadlocks, you may want to run the setup, set READ COMMITTED SNAPSHOT on for the demo database,
and try to re-create the deadlocks. The students should understand why the deadlocks that involved
shared locks cannot be created with row versioning isolation levels.
Demo1
Execution: After it is set up, open a command prompt and navigate to the Demo1 folder. Execute the
batch by double clicking the batch, or by typing the following at the command line:
Demo1
Purpose: The purpose is just to show that deadlocks do not necessarily just occur with two processes.
The cycle can contain any number of processes and resources. Here, we are using 6.
Hints:
1. What is the granularity of the locks?
2. What is the order in which the locks are taken on this granularity?
Ask: What might you do to prevent the cycle from being formed? (looking at the queries in the batch file
should reveal a very easy solution related to order).
Demo2
Note: I have found this does not always deadlock. Some builds of SQL seem to create a query plan for
the update that does not deadlock.
Execution: After it is set up, open a command prompt and navigate to the Demo2 folder. Execute the
batch by double clicking the batch file, or by typing the following from the command line:
Demo2
This demo must be run against the database where you set up the forDemo2 test table.
You may want to kill the remaining SQLCMD window after the deadlock is encountered.
Purpose: Sometimes, the order of access is not as obvious. Figure out the order of access, and what is
causing this.
Hints:
1. Look at the query plans for the two queries that are running (look in the Demo2.bat file to get
the two queries, or else, just capture batch beginning events in profiler along with your deadlock
graph).
2. Notice that 2 scans are taking place, but what object is being scanned?
3. In hint 2, if you noticed that there are 2 separate indexes being scanned, what is the order of the
columns that are indexed? Run a select to see.
4. Notice the order that results will be returned if you select from the table with the where clauses
from these queries (put only the columns in the select list that are affected by the queries). You
should never depend on this order, but this order happens often in scans, and because it
happens, this deadlock can happen.
Ask: How can you resolve the ordering to resolve this deadlock? And what will that solution affect?
Demo3
NOTE: This will ONLY deadlock on a multi-processor machine. Don’t frustrate yourself by trying to
make it deadlock on a virtual machine, or on a single processor machine.
Execution: After it is set up, open a command prompt and navigate to the Demo3 folder. Execute the
batch by double clicking, or by typing the following from the command line:
Demo3
Several SQLCMD windows will open. As deadlocks occur, these will begin to disappear, until one or two
windows are left. You will want to X off the last 1 or 2 SQLCMD windows.
Purpose: Sometimes, the order of access cannot be determined because of parallelism, and sometimes,
parallelism makes it very difficult to resolve from the deadlock graph.
Hints:
1. You may not be able to tell much about this deadlock from the deadlock graphs, and you may
get several different types of graphs on the different deadlocks that occurred. You may notice
that the victim is not even in the cycle. The first hint is that you may have to look at the XML in
the deadlock graph event, or the 1204 or 1222 information.
2. Notice that all the queries that are running are one of two updates on a single table. Look at the
query plan. Is anything introduced in the query plan that introduces an opportunity to access
resources in different order with two different executions?
3. When you look at the 1204 or 1222 information, notice that different ECIDs within the same
SPID own locks or request locks.
4. If a query plan goes parallel, is there any guarantee that the pages will be accessed in the same
order every time? Or can one thread arrive at a page at a different time relative to another
thread on different executions?
Ask:
1. Why did the query have a parallel execution plan?
2. How would you resolve the deadlock?
a. If you said to change MAXDOP to 1, that will resolve the query, but that is the cheap
way, and doesn’t address the underlying problem with the query that causes it to get a
parallel query plan in the first place … there is probably a better way.
b. Note that each update only updates a single row, but must scan the entire table to know
that. Try adding an index to the column in the where clause of the update statement,
and see if you can get a deadlock. Don’t try too long, though. Just looking at the query
plan after the index is added should tell you that the deadlock is no longer possible.
Demo4
Execution: After it is set up, open a command prompt and navigate to the Demo4 folder. Execute the
batch by double clicking, or by typing the following from the command line:
Demo4
This demo will open 2 SQLCMD windows. The deadlock will kill the first window. After the deadlock, you
will need to kill the remaining SQLCMD window.
Purpose: Demonstrate the effect of locking objects associated with tables. More is locked than just the
table rows, pages, etc. Other structures are associated with tables, and must be updated when the
tables are updated. We need to manage the order of access to these objects as well.
Hints:
1. In the deadlock graph, notice the resources that are locked, or where locks are requested.
2. Look at the query plan for the queries that are executing.
3. If a nonclustered index is used to find the row, what will then be done to access the underlying
data?
4. Are the two queries using the same nonclustered index?
5. Following through how data is accessed when a nonclustered index is used, are the objects
accessed in the same order?
6. One more thing to consider is what will happen when a column is updated that appears in the
other nonclustered index also.
This one is a little more difficult to resolve, and the cost of resolving it may be greater than dealing with
the occasional deadlock here. See what you can think of to resolve it.
NOTE: You can remove the clustered index from this and still get a deadlock. The difference is that it will
be a KEY:RID deadlock instead of the KEY:KEY deadlock we get as this is currently put together.
Demo5
Execution: After it is set up, open a command prompt and navigate to the Demo5 folder. Execute the
batch by double clicking, or by typing the following from the command line:
Demo5
This will open 3 SQLCMD windows. All 3 will close by themselves.
Hints: No hints are necessary here. This is just something I have noticed about SQL. If you didn’t get a
case in Demo3 where SQL chose a victim that was blocked, but was not part of the cycle, this will
provide an example. There will be 2 deadlock graphs here because the first victim chosen was not part
of the cycle, so rolling that process back did not resolve the deadlock.
Ask: Why did SQL choose that process as a victim?
a. I’m sure it was chosen because it was cheapest to roll back – that’s what I was counting on when
I wrote this demo, and it works consistently that way. But, I agree that the deadlock detection
process should be able to detect than that.
b. The implications of this are that other processes outside of the deadlock can be affected by
deadlocking.
Demo6
Execution: After it is set up, open a command prompt and navigate to the Demo6 folder. Execute the
batch by double clicking, or by typing the following from the command line:
Demo6
This will open 2 SQLCMD windows. Both windows will close by themselves after the deadlock is resolved.
Alternatively, you can walk through this with two query windows, just break at the points where the
waitfor commands are, and go to the other query and execute to the same point.
Note: This demo is based on a situation I went on a critsit to resolve. Note in here that I have carefully
chosen the rows selected to NOT be in the range of rows inserted. The customer’s big hang-up was that
they were inserting rows, and were not accessing the rows that were being inserted, so no cycle should
have been created.
Hints:
1. Is the deadlock graph helpful to you? It probably is only if you have seen a deadlock for this
situation before.
2. What is the lock escalation threshold for a table? mshelp://MS.SQLCC.v9/MS.SQLSVR.v9.en/udb9/html/4a24489c-e38f-4d16-9c261ab3664cdcb6.htm
3. Did you capture the lock escalation events in the trace? Were there any escalations?
4. Step through what was locked before, and after the escalation to understand how the escalation
caused the deadlock.
Download