Use of transaction in MSSQL, update several tables - sql-server

I need a sanity check ;[, a customer of mine says he is seeing data at a time when I think he should not.
example, update 2 tables
BEGIN TRANSACTION;
update table1...
update table2...
COMMIT TRANSACTION;
question - it is possible for a separate connection in the database to be triggered to read the updates to table1 before the updates in table2 are done?

Yes you can if you set the isolation level of the other reading transaction to read uncommited. https://msdn.microsoft.com/en-us/library/ms173763(v=sql.110).aspx.
It's easy to test if you start up two Sql Management Studios and run the transaction without commiting in one window, then try to select in the other window with different Isolation Levels.

Yes, it is possible, if your isolation level is set to read uncommitted.
Look at the isolation level provided by:
dbcc useroptions
https://msdn.microsoft.com/en-us/library/ms173763.aspx
http://blog.sqlauthority.com/2010/05/24/sql-server-check-the-isolation-level-with-dbcc-useroptions/

Related

sql server update blocked by another transaction, concurrency in update

Two SP's are getting executed one after another and the second one is getting blocked by first one. They both are trying to update same table. Two SP's are as following
CREATE PROCEDURE [dbo].[SP1]
Begin
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRANSACTION ImpSchd
update Table t1 .......... ................................//updating
a set of [n1,n2....n100] records
COMMIT TRANSACTION ImpSchd
SET TRANSACTION ISOLATION LEVEL
READ COMMITTED;
END
2.
CREATE PROCEDURE [dbo].[SP2]
Begin
update Table t1 .......... ................................//updating
a set of [n101,n102.....n200] records
END
My question is when sp1 is running is snapshot level isolation why is it blocking sp2 (n both are updating different set of records)?
If i run first sp for two different set of records simultaneously it
works perfectly.
How can I overcome this situation ?
If using the snapshot level isolation is to be set for each sp updating the same table then it would be a larger change.
if two sp has to update same records in a table, how should i handle that(both sp will update different columns)?
Isolation levels only are for not blocking selects,so any DML wont be affected by Isolation levels.In this case update takes IX lock on table,page followed by taking xlock on row to update.Since you are updating in bulk ,table itself might have been locked due to lock escalation.Hope this helps

SQL Server transaction and SELECT statement

I often saw many people use SELECT statement within a transaction. I often use insert/update/delete only in transaction. I just do not understand that what is the utility of putting a SELECT statement inside transaction.
I got one answer that....SELECT inside the transaction can see changes made by other previous Insert/Update/Delete statements in that transaction, a SELECT statement outside the transaction cannot.
Above statement is it true or not ?
Is this is the only reason that people put SELECT statement inside transaction? Please discuss all the reason in detail if possible. thanks
try doing this and you will understand:
Open a two new queries on SSMS (lets call it A and B from now one) and on A, create a simple table like this:
create table transTest(id int)
insert into transTest values(1)
now, do the following:
do select * from transTest in both of them. You will see the value 1
On A run:
set transaction isolation level read committed
On B run:
begin transaction
insert into transTest values(2)
On A run:
select * from transTest
you will see that the query wont finish because it is locked by the transaction on A
On B run:
commit transaction
Go back to A and you will see that the query finished
Repeat the test with
set transaction isolation level read uncommitted on A
you will see that the query wont be locked by the transaction
One of the main reasons I can think of (the only reason, in fact) is if you want to set a different isolation level, eg:
USE AdventureWorks2008R2;
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN TRANSACTION;
SELECT * FROM HumanResources.EmployeePayHistory;
SELECT * FROM HumanResources.Department;
COMMIT TRANSACTION;
For single SELECT statements though, I'm not so sure, unless you had a reason to go the other way and set READ UNCOMMITTED in cases where response time/maximising concurrency is more important than accurate or valid data.
<speculation certainty="75%"> If the single SELECT statement is inside an explicit transaction without altering the isolation levels, I'm pretty sure that will have no effect at all. Individual statements are, by themselves, transactions that are auto-committed or rolled back on error.</speculation>

Does "Set Transaction Level" require begin transaction?

In MS SQL Server, if I use "SET TRANSACTION ISOLATION LEVEL" in a stored procedure, do I need to wrap the select statements in a BEGIN/END TRANSACTION Block? Will the following work as expected?
CREATE PROCEDURE my_sproc AS
BEGIN
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
SELECT * FROM MyTable
END
The TRANSACTION ISOLATION LEVEL setting is a connection-level setting. There's no need to wrap it in a transaction.
That being said, you understand you will have dirty reads and such from this setting?
You can accomplish the same thing on a query-by-query basis by using locking hints such as:
SELECT * FROM MyTable WITH (NOLOCK)
SET TRANSACTION ISOLATION LEVEL is different to BEGIN/COMMIT/ROLLBACK
The first changes the isolation vs concurrency settings
The second defines the atomic "unit of work"
There is no direct link or interaction: different concepts

Do DB locks require transactions?

Is it true that "Every statement (select/insert/delete/update) has an isolation level regardless of transactions"?
I have a scenario in which I have set update of statements inside a transaction (ReadCommitted).
And another set not in a transaction (select statements).
In this case when first set is executing another waits.
If I set READ_COMMITTED_SNAPSHOT for DB Deadlock occurs.
ALTER DATABASE Amelio SET ALLOW_SNAPSHOT_ISOLATION ON
ALTER DATABASE Amelio SET READ_COMMITTED_SNAPSHOT ON
To solve this problem, do I need to put "Select" statements in TransactionScope?
On SQL Server every transaction has an implicit or explicit transaction level. Explicit if called with BEGIN/COMMIT/ROLLBACK TRANSACTION, implicit if nothing like this is issued.
Start your snapshot before the update query starts. Otherwise you give SQL Server no chance to prepare the changed rows into tempdb and the Update query still has the lock open.
Another way without creating a snapshot isolation is to use SELECT <columns> FROM <table> WITH (NOLOCK) which is the way to tell SQL Server to get the rows no matter what (aka READ_UNCOMMITED). As it is a query hint it changes the isolation level even with your settings. Can work if you are not bothered which state of the row is queried - however caution needs to be used when evaluating the data received.

Transaction Isolation Level Scopes

What are the scoping rules for transaction isolation levels in SQL Server 2005? I know what the different levels mean, but not how to properly apply them outside of a manually run script. I can't find a guide for practical use in production-quality code.
Obviously, the scope begins when you use a command like this:
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
But where does it end? If I set the iso level in a stored procedure and then that proc calls another, does the nested proc inherit it? Even better, if I escalate the iso level inside the nested proc is it going to carry back out into the calling proc? Do transaction commands like BEGIN TRAN, ROLLBACK, and COMMIT make any differences?
When a stored proc is called by an application or an agent job do the isolation level changes persist in some way? Do I always have to revert to the default READ COMMITTED at the end of each proc?
I would test it in different situations but I don't know how to read what the current isolation level is set to.
Run the following and see for yourself:
CREATE PROCEDURE dbo.KeepsIsolation
AS
BEGIN
PRINT 'Inside sproc that does not change isolation level';
DBCC USEROPTIONS;
END
GO
CREATE PROCEDURE dbo.ChangesIsolation
AS
BEGIN
PRINT 'Inside sproc that changes isolation level';
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
DBCC USEROPTIONS;
END
GO
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
DBCC USEROPTIONS;
EXEC dbo.KeepsIsolation;
DBCC USEROPTIONS;
EXEC dbo.ChangesIsolation;
-- demonstrates that isolation level restored to REPEATABLE READ after exiting the procedure
DBCC USEROPTIONS;
From MSDN
If you issue SET TRANSACTION ISOLATION LEVEL in a stored procedure or
trigger, when the object returns control the isolation level is reset
to the level in effect when the object was invoked. For example, if
you set REPEATABLE READ in a batch, and the batch then calls a stored
procedure that sets the isolation level to SERIALIZABLE, the isolation
level setting reverts to REPEATABLE READ when the stored procedure
returns control to the batch.
DBCC USEROPTIONS will display the current isolation level, along with all of the other SET options.
From books on line
Only one of the TRANSACTION ISOLATION
LEVEL options can be set at a time,
and it remains set for that connection
until it is explicitly changed. This
becomes the default behavior unless an
optimization option is specified at
the table level in the FROM clause of
the statement.
Isolation level does not roll back with the transaction.
Isolation level stays current even if you call into procedures and functions.
Please note there is an issue with scope of TRANSACTION LEVELS and SqlServer 2012 or earlier when high performance ADO.NET Connection Pooling is used where this can actually persist across closing of the connection:
SQL Server: Isolation level leaks across pooled connections
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/916b3d8a-c464-4ad5-8901-6f845a2a3447/sql-server-2014-reseting-isolation-level?forum=sqldatabaseengine

Resources