SQL Server Deadlock within WCF - sql-server

I am trying to resolve a deadlock issue regarding a SQL transaction (which is in a stored procedure called via LINQ-to-SQL). I used SQL Server Profiler and see that the SP is deadlocking on itself.
My client is calling a WCF method in rapid succession, which in turn calls the SP which causes a deadlock.
I have tried setting all the various SQL Server isolation levels as well as trying to set the WCF ConcurrencyMode = Single.
I continue to have many deadlock 'victims' and I am losing insert data as a consequence.
Has anybody solved this kind of problem?
Kind regards,
NickV

To get details of the deadlock, switch traceflag 1204 on. Any time a deadlock occurs, the deadlock graph, including all the details on the contended resource and what the two processes were doing is written to the SQL error log. This really helps in finding the cases of the deadlock.
Keep transcations as small as possible. Do no unneccessary work in a transaction. Never begin a transaction then wait for user input. Ensure that queries within the transaction are as efficient as possible.
Access objects in the same order. If one proc updates tbl1 first, then tbl2 after, all other procs that use those two should use them in the same order. Done properly, this can prevent deadlocks completely.
Hope that helps

Related

Solution for preventing DB deadlock in ColdFusion?

An app I am working on has to handle lots of ajax requests that needs to update some data on DB.
[Macromedia][SQLServer JDBC Driver][SQLServer]Transaction (Process ID
66) was deadlocked on lock | communication buffer resources with
another process and has been chosen as the deadlock victim. Rerun the
transaction.
For reads, I've already used the WITH (NOLOCK) hint and that prevented a lot of deadlocks on reads.
What can I do to better deal with writes?
CFLock the update code in CF?
Or is there a way to ask SQL Server to lock a Row instead of a Table?
Have anyone tried implementing CQRS? Seems to solve the problem but I am not clear on how to handle:
ID generation (right now it uses Auto Increment on DB)
How to deal with update request fail if server couldn't send the error back to the client right away.
Thanks
Here are my thoughts on this.
From the ColdFusion server side
I do believe that using named <cflock> tags around your ColdFusion code that updates the database could prevent the deadlock issue on the database server. Using a named lock would make each call single threaded. However, you could run into timeouts on the ColdFusion server side, waiting for the <cflock>, if transactions are taking a while. Handling it in this way on the ColdFusion server side may also slow down your application. You could do some load testing before and after to see how this method affects your app.
From the database server side
First of all let me say that I don't think deadlocks on the database server can be entirely prevented, just minimized and handled appropriately. I found this reference on TechNet for you - Minimizing Deadlocks. The first sentence from that page:
Although deadlocks cannot be completely avoided, following certain coding conventions can minimize the chance of generating a deadlock.
Here are the key points from that reference. They go into a bit more detail about each topic so please read the original source.
Minimizing deadlocks can increase transaction throughput and reduce system overhead because fewer transactions are:
Rolled back, undoing all the work performed by the transaction.
Resubmitted by applications because they were rolled back when deadlocked.
To help minimize deadlocks:
Access objects in the same order.
Avoid user interaction in transactions.
Keep transactions short and in one batch.
Use a lower isolation level.
Use a row versioning-based isolation level.
Set READ_COMMITTED_SNAPSHOT database option ON to enable read-committed transactions to use row versioning.
Use snapshot isolation.
Use bound connections.
The "row versioning-based isolation level" may answer your question Or is there a way to ask SQL Server to lock a Row instead of a Table?. There are some notes mentioned in the original source regarding this option.
Here are some other references that came up during my search:
Avoiding deadlock by using NOLOCK hint
How to avoid sql deadlock?
Tips to avoid deadlocks? - This one mentions being careful when using the NOLOCK hint.
The Difficulty with Deadlocks
Using Row Versioning-based Isolation Levels

What should happen when two transactions collide?

I have to implement an sql transaction as my assignment and show that i've chosen correct isolation level. The problem is im not sure what should happen when two transactions collide when isolation level is optimal. What i mean is that i dont know whether one of them should get cancelled due to the deadlock or complete successfully but have no effect (get rollbacked?). Im using MS SQL Server if it matters.
When transactions are in a deadlock situation, SQL Server chooses one as the victim of the deadlock.
That means that the victim transaction will be canceled and rollback whereas the other will keep on going as if nothing happened. SQL Server chooses the victim based on the difficulty (CPU cost) of rolling-back the victim's changes. The victim transaction will then error out with the error code 1205, which is quite explicit.
You can set the transactions' deadlock priorities yourself, as explained in the second link.
More details here :
http://technet.microsoft.com/en-us/library/ms178104(v=sql.105).aspx
And here :
http://technet.microsoft.com/en-us/library/ms186736.aspx
Btw, the fact that you use SQL Server matters a lot ! Some other DBMS would just keep the transactions in a lock forever, and others would just choose to error both transactions out. I never heard of one that would consider the transactions complete and roll them back, though...

Table partitioning in sql server - how do you ensure it wins a deadlock over queries?

The bane of my existence is when the MERGE on a table partition gets deadlocked and eventually loses.
I've tried setting the deadlock_priority to high.
I have code that kills each query hitting the tables beforehand, but sometimes I still get a query in there during those milliseconds.
I'm at a loss. Is there a good way to do this?
You must use hints in order to lock the objects that are used by the merge statement -xlock,holdlock.
My advice is to start the sql Profiler with event Deadlock Graph and try to reproduce the deadlock with a tool (I use this tool) and then to figure out why it is happening. Read this as initial information.

Is there a way to prevent from deadlocks (and what happens is one occurs and one is victimized)

I've tried to read an article on locks and deadlocks, and it just doesn't land, al the different kind of locks.
We're running 2 different processes which try to edit records in the same table.
The first process reads the new data and sends it to an external party and updates the status accordingly, the other one receives the receiveresults form the external party and updates the status accordingly.
Now we more and more get deadlocks (in which case one of the two is the victom and gets aborted). So far so good because you can anticipate on that, and try to rerun the statement, but then allways the same deadlock occurs.
So that's my first question: why does the same deadlock allways reoccur?
And second, is there a way to tell the dbms not to try and get an exclusive lock for a record (we update single records via a stored procedure) when another process is already reading and updating it, but 'wait at the side' till the other process is ready?
Or is that a much too simple thing to say about a deadlock?
and may be third, is there a way to ask LINQ to SQL which locks were causing the problem, so i get a little more insight of which parts of the process are causing the problem.
SQL Profiler is the best tool I've used to start trying to solve deadlock problems in SQL Server.
Start a trace:
On the Events Selection tab:
Uncheck all of the preselected events.
Check "Show all events".
Expand "Locks".
Check "Deadlock graph", "Lock:Deadlock", and "Lock Deadlock Chain".
Run the trace and capture the deadlock events.
View the deadlock events in SQL Profiler. The deadlock display is pretty good. You may still need to look at the raw XML to get additional details.
Using what you find from this first pass, may give you ideas on what to change, or suggest other events to trace in SQL Profiler.
As #Darryl Peterson indicates, SQL Profiler is a good tool to capture deadlock information. If you don't know when the deadlock will occur, you can set a SQL Server trace flag to capture the data.
DBCC TRACEON (1204)
When a deadlock occurs, information about the deadlock will be written to the SQL Server error log.
There are a number of ways to get a deadlock. Your first question "why does the same deadlock always occur" is probably a good sign. If the deadlock is repeatable, then you can catch it and fix it.
Regarding your second question, SQL Server is probably already telling one process to wait while the other completes. However, you can't avoid a deadlock by waiting. A deadlock is a situation where a process is trying to use a resource that is held by another process. But the other process is waiting for a resource that the first process is holding. Neither process will release a resource until it completes its work. Note that this is a simple explanation and there can be more complex deadlock conditions. The point is that processes in the deadlock will never be able to complete.
Once you learn more about the processes involved in the deadlock, you should be able to take steps to avoid it.

SQL Server 2000 Deadlock

We are experiencing some very annoying deadlock situations in a production SQL Server 2000 database.
The main setup is the following:
SQL Server 2000 Enterprise Edition.
Server is coded in C++ using ATL OLE Database.
All database objects are being accessed trough stored procedures.
All UPDATE/INSERT stored procedures wrap their internal operations in a BEGIN TRANS ... COMMIT TRANS block.
I collected some initial traces with SQL Profiler following several articles on the Internet like this one (ignore it is referring to SQL Server 2005 tools, the same principles apply). From the traces it appears to be a deadlock between two UPDATE queries.
We have taken some measures that may have reduced the likelihood of the problem from happening as:
SELECT WITH (NOLOCK). We have changed all the SELECT queries in the stored procedures to use WITH (NOLOCK). We understand the implications of having dirty reads but the data being queried is not that important since we do a lot of automatic refreshes and under normal conditions the UI will have the right values.
READ UNCOMMITTED. We have changed the transaction isolation level on the server code to be READ UNCOMMITED.
Reduced transaction scope. We have reduced the time a transaction is being held in order to minimize the probabilities of a database deadlock to take place.
We are also questioning the fact that we have a transaction inside the majority of the stored procedures (BEGIN TRANS ... COMMIT TRANS block). In this situation my guess is that the transaction isolation level is SERIALIZABLE, right? And what about if we also have a transaction isolation level specified in the source code that calls the stored procedure, which one applies?
This is a processing intensive application and we are hitting the database a lot for reads (bigger percentage) and some writes.
If this were a SQL Server 2005 database I could go with Geoff Dalgas answer on an deadlock issue concerning Stack Overflow, if that is even applicable for the issue I am running into. But upgrading to SQL Server 2005 is not, at the present time, a viable option.
As these initial attempts failed my question is: How would you go from here? What steps would you take to reduce or even avoid the deadlock from happening, or what commands/tools should I use to better expose the problem?
A few comments:
The isolation level explicitly specified in your stored procedure overrides isolatlation level of the caller.
If sp_getapplock is available on 2000, I'd use it:
http://sqlblogcasts.com/blogs/tonyrogerson/archive/2006/06/30/855.aspx
In many cases serializable isolation level increases the chance you get a deadlock.
A good resource for 2000:
http://www.code-magazine.com/article.aspx?quickid=0309101&page=1
Also some of Bart Duncan's advice might be applicable:
http://blogs.msdn.com/bartd/archive/2006/09/09/747119.aspx
In addition to Alex's answer:
Eyeball the code to see if tables are being accessed in the same order. We did this recently and reordered code to alway to parent then child. The system had grown, code and features were more complex, more user: we simply started getting deadlocks.
- See if transactions can be shortened (eg start later, finish earlier, less processing)
Identify which code you'd like not to fail and use SET DEADLOCK PRIORITY LOW in the other
We've used this (SQL 2005 has more options here) to make sure that some code will never be deadlocked and sacrificed other code.
If you have SELECT at the start of the transaction to prepare some stuff, consider HOLDLOCK (maybe UPDLOCK) to keep this locked for the duration. We use this occasionally so stop writes on this table by other processes.
The reason for the deadlocks in my setup scenario was after all the indexes. We were using (generated by default) non clustered indexes for the primary keys of the tables. Changing to clustered indexes fixed the problem.
My guess would be that you are experiencing deadlocks, either:
Because your DML(Updates probably) statements are getting escalations to table-locks, or
Different stored procedures are accessing the same tables in transactions but in a different order.
To address this, I would first examine the stored procedures, and make sure the the modifications statements have the indexes that they need.
Note: this applies to both the target tables and the source tables (despite NOLOCK, an UPDATE's source tables will get locks also. Check the query plans for scans on user stored procedures. Unlike batch or bulk operations, most user queries & DMLs work on a small subsets of the table rows and so should not be locking the entire table.
Then secondly, I would check the stored procedures to ensure that all data access in a stored procedure is being done in a consistent order (Parent -> Child is usually preferred).

Resources