When a database locks the data? - sql

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.

Related

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.

concurrent SQL statements in different transanctions

Reading up the documentation of PL-SQL CREATE TRIGGER statement in ORACLE, I went through the following bit of information:
When a trigger fires, tables that the trigger references might be
undergoing changes made by SQL statements in other users'
transactions. SQL statements running in triggers follow the same rules
that standalone SQL statements do.
It basically says the rules that would apply to two conflicting standalone SQL statements (running at the same time) are unchanged when one of the statements is performed from within a trigger.
So we have some "usual" rules about concurrent transactions and, as for these rules, the following two are mentioned:
Specifically:
Queries in the trigger see the current read-consistent materialized
view of referenced tables and any data changed in the same
transaction.
Updates in the trigger wait for existing data locks to be released
before proceeding.
These two rules look like "obscure" to non-expert users.
What do they mean more precisely?
Queries in the trigger see the current read-consistent materialized
view of referenced tables and any data changed in the same
transaction.
This means the data the trigger sees, like if it does a SELECT on a different table, represents the state of that table when the statement started running. The trigger does not see rows that have been changed by other sessions that have not been committed yet.
Updates in the trigger wait for existing data locks to be released
before proceeding.
When an Oracle statement modifies a row, the row is locked against other people changing it until that session either commits or rolls back its transaction. So if you do an insert on table A, your trigger does an update on table B, but someone else's session has already done an update on table B for that same row, your transaction will wait until they commit or rollback.

How to lock a table in SQL Server

How to lock a table in SQL Server ? I found running queries with lock and also read transactions but
confused how to use these.
I have two processes which are reading a table first then updating data in it . I want only one to update and other get this update in its read . working of my processes is as follows:-
Lock table
read data
update data if it is not updated by other process.
release Lock.
thanks
You can use TABLOCKX hint to lock entire table, but locking entire table is usually a bad idea, you might want to reconsider if you really need it.
If you want to ensure you're updating latest data, you can use rowversion column, and double check before update instead of locking entire table for reading.
In your select statement you can provide a "select for update" table hint: with (updlock). Depending on what percentage of records you are updating and their physical distribution this might perform better than a table lock.
But as Fedor Hajdu pointed out, what you probably want is an optimistic locking scheme. Check out the documentation for the READ COMMITTED SNAPSHOT isolation level. You might also find this article useful as an introduction.

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

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.