Transaction Serializable isolation level clarifications - sql

Am I right in the following?
Transaction in Serializable IsolationLevel sets read locks for select statements. There are two transactions selecting some range. Both get read locks. But then first transaction updates or adds new value inside the selected range and commits. What will happen with the second transaction? Will it fail if tries to update or add value inside selected range after first transaction has commited?

You don't say RDBMS so I am assuming a simple locking scheme with S and X locks. You say.
Transaction in Serializable
IsolationLevel sets read locks for
select statements. There are two
transactions selecting some range.
Both get read locks.
But then first transaction updates or
adds new value inside the selected
range and commits.
This wouldn't be possible if the second transaction already has a read lock on the range. It would have to wait until the second transaction released its lock. If the second transaction also attempted to update the range then deadlock would result.

yes, the second transaction will fail because the second transaction will only see datas commited before the begin of the transaction.

Related

Update table statement

have a great day to everyone.
I have some confusion about UPDATE TABLE statement in Oracle DB 12cr2.
Let's assume we have 3 users:
U1;
U2;
U3;
U1 has a table called TEST_1, and U2 and U3 both have UPDATE privilege on that table.
My question is that: If U2 and U3 try to update same rows in that particular table at the same time what will happen? How Oracle will control such kind of processes?
Thanks in advance
Although the first answer already explains very well what is the locking mechanism, let me add a bit more information.
In your case, we are talking about Row Locks (TX). Row-level locks are primarily used to prevent two transactions from modifying the same row. When a transaction needs to modify a row, a row lock is acquired.
There is no limit to the number of row locks held by a statement or transaction, and Oracle does not escalate locks from the row level to a coarser granularity. Row locking provides the finest grain locking possible and so provides the best possible concurrency and throughput.
When two transactions ( updates in your case ) are attacking the same row, the first will acquire the lock , and it won't release it until it either commits or rollback. A system change number (SCN) which is a logical, internal time stamp used by Oracle Database will be assigned to each transactions. System Change Numbers or SCNs order events that occur within the database, which is necessary to satisfy the ACID properties of a transaction.
SCNs occur in a monotonically increasing sequence. Oracle Database can use an SCN like a clock because an observed SCN indicates a logical point in time and repeated observations return equal or greater values. If one event has a lower SCN than another event, then it occurred at an earlier time with respect to the database. Several events may share the same SCN, which means that they occurred at the same time with respect to the database.
Every transaction has an SCN. For example, if a transaction updates a row, then the database records the SCN at which this update occurred. Other modifications in this transaction have the same SCN. When a transaction commits, the database records an SCN for this commit.
Oracle Database increments SCNs in the system global area (SGA). When a transaction modifies data, the database writes a new SCN to the undo data segment assigned to the transaction. The log writer process then writes the commit record of the transaction immediately to the online redo log. The commit record has the unique SCN of the transaction. Oracle Database also uses SCNs as part of its instance recovery and media recovery mechanisms.
When two transactions occur at the very same time, for example the same second, the one which its timestamp is sooner is the one acquiring lock. Keep in mind that TIMESTAMP stores fractional_seconds_precision which specifies the number of digits in the fractional part of a SECOND. This fraction can be a number in the range 0 to 9.
In short One of the three users will acquire a lock on the table while updating it (whichever users executes the query first by micro secs differences) and rest of the two users have to wait for U1 to commit and release the lock, So now U2 or U3 will get updated data to work upon.
Snippet from another article:
COMMIT
When a COMMIT statement is issued to the database, the transaction has ended, and the following results are true:
All work done by the transaction becomes permanent.
Other users can see changes in data made by the transaction.
Any locks acquired by the transaction are released.

Some clarifications on different Isolation level in database transaction?

Below is the statement written from Wikipedia's Isolation article about REPEATABLE READS
In this isolation level, a lock-based concurrency control DBMS implementation keeps read and write locks (acquired on selected data)
until the end of the transaction. However, range-locks are not managed, so the phantom reads phenomenon can occur (see below).
My question here is when does the the transaction begin and end respectively.
If we take the example of Non-repeatable reads with REPEATABLE READS Isolation level at the same link , as per my understanding trnsaction 1 begin
when first query is fired i.e SELECT * FROM users WHERE id = 1. DBMS will keep the lock on the users table until and unless transaction gets end.
here By end I mean is when connection gets rolledback or commited not on the completion of SELECT * FROM users WHERE id = 1. Till that time
Transaction 2 will wait Right?
Question 2 :- Now if we consider the isolation level and thier behaviour as given below (at the same link)
Isolation level Dirty reads Non-repeatable Phantoms
Read Uncommitted may occur may occur may occur
Read Committed - may occur may occur
Repeatable Read - may occur -
Serializable - - -
As per my understanding Most reliable is Serializable then Repeatable Read and then Read Committed but still i have seen aplications using Read Committed. Is that because
of performance of Serializable and Repeatable Read is bad in comparison to Read Committed because in serializable it will be sequential and in case
of transaction has to wait for release of lock by another transaction. Right? So to get best of all three we can use isolation
level as Read Committed with SELECT FOR UPDATE (to achieve repeatable read).Not sure how we can achieve phantom read if we want , in case of read commited
isolation level?
Oracle does not support the REPEATABLE READ isolation level. However, SQL Server does - and it does place locks on all rows selected by the transaction until it ends (ie: it's committed or rolled back). So you are correct, this will indeed make other transactions wait (if they are updating the locked data) and can be detrimental to concurrency.
As for question 2: Yes, the higher the isolation level, the worse your concurrent transactions will perform because they have to wait for more locks to be released. I am not sure what you mean by "getting the best of all three" by using SELECT FOR UPDATE because SELECT FOR UPDATE will place row locks on all selected rows.
And finally, here's a quote from Oracle's manual on phantom reads:
[phantom reads occur when] a transaction reruns a query returning a set of rows that satisfies a search condition and finds that another committed transaction has inserted additional rows that satisfy the condition.
For example, a transaction queries the number of employees. Five minutes later it performs the same query, but now the number has increased by one because another user inserted a record for a new hire. More data satisfies the query criteria than before, but unlike in a fuzzy read the previously read data is unchanged.
Reference:
Data Concurrency and Consistency (Oracle)
SET TRANSACTION LEVEL (SQL Server)

READ UNCOMMITTED and Estimates

From time to time, I want to run a stored procedure to get a rough estimate of how many records in two or three different tables satisfy some criteria. If during this estimate new records are added, deleted or updated, there is not really a problem (I just want a rough estimate). That being, I can afford for this process using SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED. However, I have two questions about this:
1) Since I am only using SELECT COUNT(*) instructions, do I really need to wrap these statement in a BEGIN/COMMIT TRANSACTION block?
2) Do I need to SET TRANSACTION ISOLATION LEVEL READ COMMITTED back in the end of the stored procedure, or will this be automatically set once its execution ends?
No. Reads don't need to be in a transaction
The SET is scoped only for the stored procedure. See my answer here: Is it okay if from within one stored procedure I call another one that sets a lower transaction isolation level?. However, you'd use the NOLOCK hint rather then SET: SELECT COUNT(*) FROM myTable WITH (NOLOCK).
If you want an approximate count without WHERE filters, then use sys.dm_db_partition_stats. See my answer here: Fastest way to count exact number of rows in a very large table?
1) No. It uses implicit transaction for each statement if you do not specify the transaction scope. You do not have to put explicit transaction scope for making 'set transaction isolation level to work'.
2) You don't have to reset it to original. It will be taken care by SQL Server. Please refer to this SO entry: Transaction Isolation Level Scopes

race condition UPDATE modification of credit column - what happens on rollback?

ok, I tried searching and have not found an answer to this - I am curious how the ROLLBACK handles race conditions. For example:
If I have a table (CompanyAccount) which keeps track of how many credits an company has available for purchase (there is only one row in a database table per company) and there are potentially multiple users from the same company who can decrement the credits from the single company account, what happens in case of an error when a ROLLBACK occurs?
Example:
Assumptions: I have written the update properly to calculate the "Credit" new balance instead of guessing what the new credit balance is (i.e. we don't try to tell the UPDATE statement what the new Credit balance/value is, we say take whatever is in the credit column and subtract my decrement value in the UPDATE statement)...
here is an example of how the update statement is written:
UPDATE dbo.CompanyAccount
SET Credit = Credit - #DecrementAmount
WHERE CompanyAccountId = #CompanyAccountId
If the "Credit" column has 10,000 credits. User A causes a decrement of 4,000 credits and User B causes a decrement of 1000 credits. For some reason a rollback is triggered during User A's decrement (there are about a 1/2 dozen more tables with rows getting INSERTED during the TRANSACTION). If User A wins the race condition and the new balance is 6,000 (but not yet COMMIT'ed) what happens if User B's decrement occurs before the rollback is applied? does the balance column go from 6,000 to 5,000 and then gets ROLLBACK to 10,000?
I am not too clear on how the ROLLBACK will handle this. Perhaps I am over-simplifying. Can someone please tell me if I misunderstand how ROLLBACK will work or if there are other risks I need to worry about for this style.
Thanks for your input.
In the example you have given there will be no problem.
The first transaction will have an exclusive lock meaning the second one can not modify that row until after the first one has committed or rolled back. It will just have to wait (blocked) until the lock is released.
It gets a bit more complicated if you have multiple statements. You should probably read up on different isolation levels and how they can allow or prevent such phenomena as "lost updates".
Rollback is part of the transaction and locks will be maintained during the rollback. The *A*tomic in ACID.
User B will not start until all locks are released.
What happens:
User A locks rows
User B won't see the rows until locks are released
User A rolls back, release locks, changes never happened.
User B sees the rows. -1000 will result in 9000
However, if User B has already read the balance then it my be inconsistent when it comes to UPDATE. It depends on what you're actually doing and in what order, hence the need to understand isolation levels (and the issues with phantom and non-repeatable reads)
An alternative to SERIALIZABLE or REPEATABLE READ may to use sp_getapplock in transaction mode to semaphore parts of the transaction.

Records write locked on a RepeatableRead

I have a SQL Server query (using the LLBL ORM, if that is important to the question) that is doing a large fetch on a set of related tables.
This query is being performed in a transaction with the Isolation Level of Repeatable Read, and is being filtered by two 'state' columns in the main table of the query.
Will the records being 'write locked' only be those that match the filter in the main table, or will all records be effectively write locked until the fetch has completed? I am guessing the later will be required to ensure no new records are added to the result set during the transaction.
to ensure no new records are added to
the result set during the transaction
This requires Serializable isolation level. Repeatable Read only ensures that the rows read will be able to read again later in the transaction, but does not prevent a concurrent transaction from inserting new rows and those new rows will be visible, in the original transaction, after they are committed by the insert. Under Serializable Read the locks will extend to ranges, so no new records that satisfy the filter will appear. Depending on the table schema (indexes available) the restriction may extend to the entire table(s).
You should give some serious consideration to doing everything under Snapshot Isolation too, this resolves almost all known anomalies, but is more expensive on resource, see Row Versioning Resource Usage.