Can a readcommitted isolation level ever result in a deadlock (Sql Server)? - sql

My understanding of deadlocks is - two processes trying to contend for same resource - typically two processes trying to 'write' to same row of data. If all one process is doing is reading the data - and the other process is updating the data, how is that a resource contention? Yet, in our database, which is set to the default transaction level 'ReadCommitted', we are seeing several deadlock exceptions.
ReadComitted definitin - Data that has been modified (but not yet committed) cannot be read. That is fine – but should SQL Server throw a deadlock exception if it encounters this ‘dirty read’ taking place?
Anybody have real world experience with this scenario? I found a blog post (by the stackoverflow developer, no less :) claiming that this might be true.

ReadCommitted Transaction Isolation Level initially obtains a Shared Lock on a resource i.e while reading the row but when we try to UPDATE the row it obtains an Exclusive lock on the resources. Multiple user can have shared locks on same rows and it wont effect but as soon as One user tries to update a row It gets an Exclusive Lock on the row which can result in A dead lock when a user who could initially see the record because of the shared locks on the row but now when the user tries to update it It already has an exclusive lock on it by the 1st user. Imagine a scenario where User1 and User2 Both has shared locks and when they try to update some records they both get Exclusive locks on the rows which other user need to commit the transaction. this will result in a DEAD LOCK.
In case of a DeadLock if the Priority Level is not set SQL Server will wait for sometime and then it will RollBack the transaction which is cheaper to rollback.
Edit
Yes if User1 is only reading data and User2 trys to Update some data and there a non-clustered index on that table, it is possible.
User1 is reading Some Data and obtains a shared lock on the non-clustered index in order to perform a lookup, and then tries to obtain a shared lock on the page contianing the data in order to return the data itself.
User2 who is writing/Updating first obtains an exlusive lock on the database page containing the data, and then attempts to obtain an exclusive lock on the index in order to update the index.

Yes, it can happen. Imagine you have two processes each with its own transaction. The first updates TableA then tries to update TableB. The second updates TableB then tries to update TableA. If you're unlucky, both processes manage to complete their first step and then wait indefinitely to the other in order to complete the second step.
Incidentally, that's one of the most common ways to avoid deadlocks: be consistent in order in which you update your table. If both processes updated TableA first then TableB, the deadlock wouldn't occur.

Related

Transaction rollback VS Delete Records

Looking for some insights on using Transaction or Delete queries when the subsequent request fails. In brief, in my application, I'm inserting into two tables by calling two stored procedures and the inserted data would be uploaded into two REST APIs. If anyone of the REST API is failed I have to rollback the details entered into database.
So which approach is suitable? Either to use SQL transaction or Delete the inserted records through database Procedure.
This is and ideal situation to use transaction. How do you know it?
Let's say you insert some rows, then do API call, then try to delete inserted rows. What will happen in that case?
Inserted rows are readable already (even without dirty read enabled) - they are just normal rows in database. So all the queries made until you finish you request, will relate to this rows as well.
What will happen if you fail to delete the rows? Exactly, they will just stay in database. Here you have improper data. Bad.
Use transaction approach - start transaction and commit it only when you finished API call, this way you will ensure, that your database contains proper data at all times.

When a database locks the data?

I just want to have this clear. I know that when a Session A tries to update a cell that is currently in use by Session B, the database lock that data and Session A have to wait for Session B to finish.
This can happen with SQL Statements like UPDATE, but, what happens if Session B are performing a SELECT
Does Session A have to wait too ?
"if Session B are performing a SELECT" - depends on the isolation level of the session B.
If "repeatable read" and no MVCC-DBMS or "serializable" then a record read in session B must be locked against changes, otherwise the condition of a second identical read can not be met.
No locking is needed if the only transactions on the database are SELECTs.
Locking is needed to "protect" rows when data is being changed. They are not needed when data is only being read. So, if one of the sessions is doing a data modification (such as an UPDATE), then it could block a SELECT.
As a note: databases have no concept of "cells". Locks (depending on the database) are available on the table, page, and row levels.
I should point out that this is for "standard" database technology. Column-oriented databases operate a bit differently.

What are the performance consequences of different isolation levels in PostgreSQL?

I am writing an archival script (in Python using psycopg2) that needs to pull a very large amount of data out of a PostgreSQL database (9.4), process, upload and then delete it from the database.
I start a transaction, execute a select statement to create a named cursor, fetch N rows at a time from the cursor and do processing and uploading of parts (using S3 multipart upload). Once the cursor is depleted and no errors occurred, I finalize the upload and execute a delete statement using the same conditions as I did in select. If delete succeeds, I commit the transaction.
The database is being actively written to and it is important that both the same rows get archived and deleted and that reads and writes to the database (including the table being archived) continue uninterrupted. That said, the tables being archived contain logs, so existing records are never modified, only new records are added.
So the questions I have are:
What level of isolation should I use to ensure same rows get archived and deleted?
What impact will these operations have on database read/write ability? Does anything get write or read locked in the process I described above?
You have two good options:
Get the data with
SELECT ... FOR UPDATE
so that the rows get locked. Then the are guaranteed to be there when you delete them.
Use
DELETE FROM ... RETURNING *
Then insert the returned rows into your archive.
The second solution is better, because you need only one statement.
Nothing bad can happen. If the transaction fails for whatever reason, no row will be deleted.
You can use the default READ COMMITTED isolation level for both solutions.

MS ACCESS Lock a table during update, blocking

How can I lock a table preventing other users querying it while I update its contents?
Currently my data is updated by wiping the table and re-populating it (i know, its not the best way to update data, but the source data has no unique key to do a record by record update and this is the only way). There exists the unlikely, but possible scenario where a user my access the table in the middle of the update and catch it while it is empty thus returning bad info.
Is there at the SQL (or code) level a way to create a blocking statement that will wait for a DB update to complete prior to querying?
Access has very little locking capabilities. Unless you're storing your data in a different backend, you only can set a database-wide lock or no lock at all.
There is some locking capability setting table locks when the table structure of a table is being changed, but as far as I can find, that's not available to the user (neither through the GUI nor through VBA)
Note that both ADO and DAO support locking (in ADO by setting the IsolationLevel, in DAO by setting dbDenyRead + dbDenyWrite when executing the query), but in my short testing, these options do absolutely nothing in Access.

Can a simple SELECT statement block processes when there is no open transaction?

I encountered a weird scenario a couple of days ago, when a simple SELECT statement that returned 4 rows of data was causing a blocking chain in SQL server. There was no open transactions. Any inkling why this might occur?
Yes a simple SELECT statement can endup in deadlock , Imagine a
scenario where User1 is only reading data and User2 trys to Update
some data and there a non-clustered index on that table, it is
possible.
1) User1 is reading Some Data and obtains a shared lock on the
non-clustered index in order to perform a lookup, and then tries to
obtain a shared lock on the page contianing the data in order to
return the data itself.
2) User2 who is writing/Updating first obtains an exlusive lock on the
database page containing the data, and then attempts to obtain an
exclusive lock on the index in order to update the index.
Read here to learn more about locking in sql-server.