Oracle: Which is Lock is acquired by Serializable isolation level - oracle

What I am trying to establish is whether there is any direct relation between Isolation Levels and Locks. So, let's say I started a transaction with a Serializable isolation level then will Oracle by default acquire some type of "Table" lock on all the tables listed in that transaction, if so then what it is?
I couldn't find any direct answer to this question, but my own understanding from reading many online docs is that there is no direct relation between Isolation Levels and Locks. Locks will be acquired based on specific SQL statement present in the transaction - and not based on whether the transaction isolation level is Read Committed or Serializable, so if there is a DML then Read Exclusive table lock (RX) will be acquired and if there is a statement like LOCK TABLE table IN EXCLUSIVE MODE; then Exclusive table lock (X) will be acquired.
Please note that this question is very specific to Oracle and then very specific on which lock is acquired by Serializable isolation level. In no way I am looking for answers related to Isolation Levels and Locks available in Oracle, I have read the online docs and understand them.

I asked same question on Ask Tom as well and graciously Ask Tom has confirmed my understanding - in short, there is no direct relation between Isolation Levels and Locks. Locks will be acquired based on specific SQL statement present in the transaction - and not based on whether the transaction isolation level is Read Committed or Serializable, so if there is a DML then Read Exclusive table lock (RX) will be acquired and if there is a statement like LOCK TABLE table IN EXCLUSIVE MODE; then Exclusive table lock (X) will be acquired.
Here is the link of AT answer: https://asktom.oracle.com/pls/apex/asktom.search?tag=oracle-which-lock-is-acquired-by-serializable-isolation-level

Related

Emulate shared row locks in Oracle DB?

Is it possible to somehow emulate shared row locks (as they exist in other DBMS, like PostgreSQL) in Oracle DB?
That is row locks, that allow other session to obtain the same (shared) locks on the same row, but prevent them from obtaining exclusive locks. Also, an existing exclusive lock on a row prevent others obtaining any kind of row lock.
For reference: Oracle supports only exclusive row locks.
Note: The question is about Oracle DB 11.2g

Spring Database Lock: Need help in understanding the condition for database deadlock

I am using Spring-Data-Jpa and using #Lock annotation(PESSIMISTIC_WRITE) for taking database(Oracle) locks. I need help in understanding that whether the following scenario can lead to a database dead lock.
Transaction 1(PROPAGATION_REQUIRES_NEW, ISOLATION_DEFAULT) one takes a database lock over say Teacher table(say lock is taken over row with id=1). It tries to insert a new record in the child table say Meeting. No update is done on the Teacher table
While Transaction 1 is in progress. Transaction 2(PROPAGATION_REQUIRED, ISOLATION_DEFAULT) tries to update the Teacher table(row with id=1). It does not take a database lock.
Since the lock is taken over row with id 1. Transaction 2 has to wait for transaction 1 to get over.
Can this condition lead to a database dead lock?
I think your case will lead to a database lock, yes, but no deadlock will be triggered. And database lock is something we expect to happen to achieve ACID transaction.

Disable queries on table while updating

I have a pl/sql script that clears (via delete from statement) and populates several depended tables like this:
delete from table-A
insert into table-A values(...)
delete from table-B
insert into table-B values(...)
These operations require ~ 10 seconds to complete and I'd like to stop all sql queries that try to read data from table-A or table-B while tables are updating. These queries should stop and continue execution when table-A and table-B are completely updated.
What is the proper way to do this?
As others have pointed out, Oracle's basic concurrency model is that writers do not block readers and readers do not block writers. You can't stop a simple select from running. Your queries will see the data as of the SCN that they started executing (assuming that you're using the default read committed transaction isolation level) so they will have a consistent view of the data before your updates started.
You could potentially acquire a custom named lock using dbms_lock.request. You would need to acquire this lock before running your updates and every session that queries the tables would also need to acquire the lock before it starts to query the tables. That will, obviously, decrease the scalability of your application but it will accomplish what you appear to be asking for. Presumably, the sessions doing queries can acquire the lock in shared mode while the session doing the updates would need to acquire it in exclusive mode.

Need help understanding the behaviour of SELECT ... FOR UPDATE causing a deadlock

I have two concurrent transactions executing this bit of code (simplified for illustration purposes):
#Transactional
public void deleteAccounts() {
List<User> users = em.createQuery("select u from User", User.class)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.getResultList();
for (User user : users) {
em.remove(user);
}
}
My understanding is that one of the transactions, say transaction A, should execute the SELECT first, lock all the rows it needs and then go on with the DELETEs while the other transaction should wait for A's commit before performing the SELECT. However, this code is deadlocking. Where am I wrong?
The USER table probably has a lot of foreign keys referring to it. If any of them are un-indexed Oracle will lock the entire child table while it deletes the row from the parent table. If multiple statements run at the same time, even for a different user, the same child tables will be locked. Since the order of those recursive operations cannot be controlled it is possible that multiple sessions will lock the same resources in a different order, causing a deadlock.
See this section in the Concepts manual for more information.
To resolve this, add indexes to any un-indexed foreign keys. If the column names are standard a script like this could help you find potential candidates:
--Find un-indexed foreign keys.
--
--Foreign keys.
select owner, table_name
from dba_constraints
where r_constraint_name = 'USER_ID_PK'
and r_owner = 'THE_SCHEMA_NAME'
minus
--Tables with an index on the relevant column.
select table_owner, table_name
from dba_ind_columns
where column_name = 'USER_ID';
When you use a PESSIMISTIC_WRITE JPA generally traslate it to SELECT FOR UPDATE this make a lock in the database, not necessary for a row it depends of the database and how you configure the lock, by default the lock is by page or block not for row, so check your database documentation to confirm the how your database make the lock, also you can change it so you can apply the lock for a row.
When you call the method deleteAccounts it starts a new transaction and the lock will be active until the transaction commit (or rollback) in this case when the method has finished, if other transaction want to acquire the same lock it can't and I think this is why you have the dead lock, I suggest you to try annother mechanism maybe an optimistic lock, or a lock by entity.
You can try given a timeout to the acquire the lock so:
em.createQuery("select u from User", User.class)
.setLockMode(LockModeType.PESSIMISTIC_WRITE)
.setHint("javax.persistence.lock.timeout", 5000)
.getResultList();
I found a good article that explains better this error, it is cause by the database:
Oracle automatically detects deadlocks and resolves them by rolling
back one of the transactions/statements involved in the deadlock, thus
releasing one set of resources/data locked by that transaction. The
session that is rolled back will observe Oracle error: ORA-00060:
deadlock detected while waiting for resource. Oracle will also produce
detailed information in a trace file under database's UDUMP directory.
Most commonly these deadlocks are caused by the applications that
involve multi table updates in the same transaction and multiple
applications/transactions are acting on the same table at the same
time. These multi-table deadlocks can be avoided by locking tables in
same order in all applications/transactions, thus preventing a
deadlock condition.

What are different types of locks in oracle

Please anyone explain locking mode in Oracle i.e. Share, Exclusive and Update lock. I found many theories on this and according to that
Share lock : Nobody can change data,Read only purpose
Exclusive lock : Only one user/connection are allow to change the data.
Update lock : Rows are locked till user made commit/rollback.
Then, I tried shared to check how it works
SQL> lock table emp in share mode;
Table(s) Locked.
SQL> update emp set sal=sal+10;
14 rows updated.
Then, I found that, user can change data after share lock. Then, what makes it different from exclusive lock and update lock.
Another question, how Update lock and exclusive lock are different with each other, even they seems almost equivalent.
Posting explanation for future visitors, and it also gives the answer.
Shared lock
Before I begin let me first say that there are 5 types of table locks - row shared, row exclusive, shared, shared row exclusive and exclusive. And shared lock is one among these. Also, please note that there are row locks, which are different than table locks. Follow the link I have provided in end to read about all this.
A shared lock is acquired on the table specified in following statement – LOCK TABLE table IN SHARE MODE;
This lock prevents other transactions from getting “row exclusive” (this lock is used by INSERT, UPDATE and DELETE statement), “shared row exclusive” and “exclusive” table locks, otherwise everything is permitted.
So, this means that a shared lock will block other transactions from executing INSERT, UPDATE and DELETE statements on that table but will allow other transactions to update the rows using “SELECT … FOR UPDATE” statement because for this statement a “row shared” lock is required, and it is permitted when a “shared” lock is required.
Below table is a good summary of locks and what's permitted.
Since many users will follow this question so I decided to go one more step further and put my learning notes, I hope folks will be benefited from it:
Source of this information and also excellent reading about Oracle locks.
It's very well explained in the documentation: http://docs.oracle.com/cd/E11882_01/server.112/e41084/ap_locks001.htm#SQLRF55502
In your example you locked the table in shared mode. This does not prevent other sessions locking the same object in shared mode, but it does prevent them from locking it in exclusive mode so you could not drop the table (which requires an exclusive lock) while it is being updated (which has a shared lock).

Resources