About Me

My photo
Mumbai, Maharastra, India
He has more than 7.6 years of experience in the software development. He has spent most of the times in web/desktop application development. He has sound knowledge in various database concepts. You can reach him at viki.keshari@gmail.com https://www.linkedin.com/in/vikrammahapatra/ https://twitter.com/VikramMahapatra http://www.facebook.com/viki.keshari

Search This Blog

Thursday, January 9, 2014

Nested Transaction III: Killing open transaction

Previous Article on Transaction:

We will see how to kill open transaction in a particular session, here below I m writing a block which will create two open transaction
For writing this script, I opened a session, just a new sql window, and executed the below script  

begin tran firstTran
      insert into TAB_NestedTransaction_Demo values(1)
    
      begin tran secondTran
            insert into TAB_NestedTransaction_Demo values(2)

Command(s) completed successfully.

With the help of DBCC OPENTRAN command, we can check the session and the transaction detail of open transaction. Here we firing DBCC command to check the session and transaction

dbcc opentran           
Transaction information for database 'Sparsh'.

Oldest active transaction:
    SPID (server process ID): 53
    UID (user ID) : -1
    Name          : outerTran
    LSN           : (1366:4126:1)
    Start time    : Jan  9 2014  8:51:38:750PM
    SID           : 0xa578602ded7cd44c96d1358f246a1c79
DBCC execution completed. If DBCC printed error messages, contact your system administrator.

So from the output of DBCC we can see that the open transaction “outerTran” exist in the session 53.

So now to kill this transaction we need to kill the session but you cannot kill a session begin inside the same session environment, so to kill a particular session, you need to open a new session and fire KILL command with session ID.

So here we opened a  new SQL window and fire the kill command with session id 53 where the transaction are in active state.

kill 53
Command(s) completed successfully

After killing the session if we fire DBCC OPENTRAN, we can see that there are no active transaction alive.

dbcc opentran
No active open transactions.

Every code is genius at least once in his life. The real geniuses are programmers who keep those codes bright everlastingly.

Post Reference: Vikram Aristocratic Elfin Share

Some witty finding on Nested Transaction II: Partial Rollback with Savepoint


Here in this article we will see how we can rollback a portion of transaction keeping other part as it is for commit. For revelation we are again taking the same EMP table, let see first, how many records are present in it.
  
select * from emp
emp_id      ename      dept_id
----------- ---------- -----------
1           neha       1
2           richa      1
3           sidhika    2
4           Sneha      1
6           Kavita     3

(5 row(s) affected)

Now I am writing a block which is nested by two transaction, in the inner transaction after inserting record with emp_id 8, I m trying to rollback the inner transaction while keeping the first (outer) transaction as it is for commit.

set nocount on
go
begin tran
      insert into emp values(7,'Sanjana',2)
      begin tran
            insert into emp values(8,'Monica',2)
            rollback tran
commit tran

Msg 3902, Level 16, State 1, Line 6
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

select * from emp
emp_id      ename      dept_id
----------- ---------- -----------
1           neha       1
2           richa      1
3           sidhika    2
4           Sneha      1
6           Kavita     3

(5 row(s) affected)

Here we saw, the first call to ROLLBACK TRAN in inner transaction rollback both the transaction the outer and inner one. So there must be no insert into the table emp. We can also check this using @@trancount.

Let’s print @@trancount in the same script.

set nocount on
go
begin tran
      insert into emp values(7,'Sanjana',2)
      print 'Trancount : ' + cast(@@trancount as varchar)
      begin tran
            insert into emp values(8,'Monica',2)
            print 'Trancount : ' + cast(@@trancount as varchar)
            rollback tran
      print'Trancount : ' + cast(@@trancount as varchar)
commit tran

Trancount : 1
Trancount : 2
Trancount : 0
Msg 3902, Level 16, State 1, Line 9
The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.

So after the rollback fired, both the opened transaction closed and we get @@trancount as 0.

Now let’s define the transaction with name so that we can explicitly mention which transaction to rollback

set nocount on
go
begin tran   outerTran
      insert into emp values(7,'Sanjana',2)
      print 'Trancount : ' + cast(@@trancount as varchar)
      begin tran InnerTran
            insert into emp values(8,'Monica',2)
            print 'Trancount : ' + cast(@@trancount as varchar)
            rollback tran  InnerTran
      print'Trancount : ' + cast(@@trancount as varchar)
commit tran outerTran

Trancount : 1
Trancount : 2
Msg 6401, Level 16, State 1, Line 7
Cannot roll back InnerTran. No transaction or savepoint of that name was found.
Trancount : 2

select * from emp
emp_id      ename      dept_id
----------- ---------- -----------
1           neha       1
2           richa      1
3           sidhika    2
4           Sneha      1
6           Kavita     3
7           Sanjana    2
8           Monica     2

So we can rollback on inner transaction has no effect and the out transaction committed both the insert in spite of having rollback on second transaction.

I am deleting employee with emp_id 7 and 8

delete emp where emp_id=7 or emp_id=8

Here I am using Savepoint, this will allow to rollback some part of transaction leaving other part as it is for commit. One more thing, one can’t use savepoint without transaction. Let’s see, how we are using savepoint in our earlier code..

set nocount on
go
begin tran   outerTran
      insert into emp values(7,'Sanjana',2)
      print 'Trancount : ' + cast(@@trancount as varchar)
      begin tran InnerTran
            save tran ManishPoint
            insert into emp values(8,'Monica',2)
            print 'Trancount : ' + cast(@@trancount as varchar)
            rollback tran  ManishPoint
      print'Trancount : ' + cast(@@trancount as varchar)
commit tran outerTran

select * from emp

emp_id      ename      dept_id
----------- ---------- -----------
1           neha       1
2           richa      1
3           sidhika    2
4           Sneha      1
6           Kavita     3
7           Sanjana    2 

Now you can see the inner transaction which was trying to insert employee with id 8 get rollbacked and leaving other part of transaction as it is to commit.

Watch your thought, they became logic
Watch your logic, they became code
Watch your code, they became program
Watch your program, crop up new thought

SDLC…cont..

Post Reference: Vikram Aristocratic Elfin Share

Wednesday, January 8, 2014

Some witty finding on Nested Transaction with Rollback and Commit

When we have transaction block defined inside transaction block, we call it as Nested transaction, and here in this article we will see how Rollback and Commit works with Nested transaction. Let’s start with Rollback
   
Nested Transaction with Rollback

We are creating a table with a single column for our demo.

create table TAB_NestedTransaction_Demo
(col1 int)
Command(s) completed successfully.

Now lets start with our transaction block, here we are creating a transaction block named “firstTran”, inside it we are first inserting a record in newly created table TAB_NestedTransaction_Demo thereafter again we are creating one more transaction block named “secondTran” in inside the second transaction block we are inserting one more record in “TAB_NestedTransaction_Demo” table. Then we are rollbacking the second transaction and checking the transaction count (number of active transaction)

begin tran firstTran
      insert into TAB_NestedTransaction_Demo values(1)
     
      begin tran secondTran
            insert into TAB_NestedTransaction_Demo values(2)           
      rollback tran secondTran
      select @@TRANCOUNT     

Msg 6401, Level 16, State 1, Line 6
Cannot roll back secondTran. No transaction or savepoint of that name was found.

No of Active Tran
-----------------
2

The above script throw an error while trying to rollback the inner transaction “secondTran”. And we can see the transaction count comes out as 2. That means none of the transaction gets rollbacked even after explicitly rollbacking innner transaction “secondTran”.Lets now execute the below lines and see the finding

rollback tran firstTran
go
select @@TRANCOUNT as [No of Active Tran]
No of Active Tran
-----------------
0

These two lines successfully gets executed and we can see transaction count comes out to be zero now.

Conclusion : from the above example we can see that  SQL server will allow you to rollback only the outer transaction and rollback of outer transaction will rollback all nested transactions and hence making the transaction count to zero.

Nested  Transaction with Commit

Lets now check out nested transaction with COMMIT, here we can see in the below code block we open first transaction firstTran then we inserted a record in TAB_NestedTransaction_Demo then we are opening one more transation inside the outer one and inserting one more record to the same table, thereafter we are committed second transaction. Then we rollback first transaction.
   
begin tran firstTran
      insert into TAB_NestedTransaction_Demo values(1)
      begin tran secondTran
            select @@TRANCOUNT [No of Active Tran from Inner]
            insert into TAB_NestedTransaction_Demo values(2)
      commit tran secondTran
      select @@TRANCOUNT [No of Active Tran from Outer]
rollback

[No of Active Tran from Inner]
-----------
2

[No of Active Tran from Outer]
-----------
1

Now lets query TAB_NestedTransaction_Demo.

select * from TAB_NestedTransaction_Demo

col1
-----------

(0 row(s) affected)

To our sock what we saw there is no records which get inserted in the table even after committing the inner transaction after inserting record into the table.
One more finding which we can see is, after committing the inner transaction, the transaction count reduced to one. Which says that the inner transaction is committed, but when doing select query on table, after executing last rollback statement, we found no records in the table?

Conclusion:  There is no effect in committing the inner transaction in Nested Transaction. And you cannot rollback inner transaction.  


Ask a programmer about his experience of living with code, he will say love, grace and beautiful…   

Post Reference: Vikram Aristocratic Elfin Share

Monday, January 6, 2014

Plan Caching VI - Forced Parameterization in Adhoc Queries

Read Previous Post:
In the last article we saw that the datatype of constant is selected on fly depending upon the constant value by SQL Server, due to which the cached Prepared Parameterized plan is not been used by a similar query with constant little different.

Just check this, below example.  

dbcc FREEPROCCACHE
DBCC DROPCLEANBUFFERS
Go

select * from emp where emp_id = 1
go

Then executing this sys.dm_exec_cached_plans query

select usecounts, cacheobjtype, objtype, [text]
from sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
where usecounts > 0
AND
[text] not like '%dm_exec_cached_plans%' and [text] not like  '%dm_exec_sql_text%'
order by usecounts desc
go

usecounts cacheobjtype  objtype  text
--------  ------------- -------- --------------------------------------------
1         Compiled Plan Prepared (@1 tinyint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 1

From the output we can see that the constant used in query where predict is being treated as tinyint. So the datatype is of the constant is being selected on fly by SQL Server while making a prepared Parameterized cache plan.

Now let’s query the same select with contact value ranging out of tiny data type.

select * from emp where emp_id = 700
go
 
Then executing this sys.dm_exec_cached_plans query

select usecounts, cacheobjtype, objtype, [text]
from sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
where usecounts > 0
AND
[text] not like '%dm_exec_cached_plans%' and [text] not like  '%dm_exec_sql_text%'
order by usecounts desc
go

usecounts cacheobjtype  objtype  text
--------  ------------- -------- --------------------------------------------
1         Compiled Plan Prepared (@1 tinyint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 1
1         Compiled Plan Prepared (@1 smallint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 700

Here we can see from the output that it has not used the Prepared plan which gets generated when we executed query with predicate constant value as 1 and generate a new prepared plan and cached in memory; this time the constant is replaced by parameter and the type for the parameter is choosed as smallInt unlike tinyint in previous case.

So we get two prepared queries plan with two different parameter data type. So SQL Server is not making use of existing Parameterized cached plan.

The only way to force SQL Server to use the same data type  for both the queries is to enable PARAMETERIZED FORCED for the database.

dbcc FREEPROCCACHE
DBCC DROPCLEANBUFFERS
Go

alter database sparsh set parameterization forced;
go

Here we have set PARAMETERIZATION FORCED enabled. Once this is done SQL Server treats every kind constants as just a set of parameters.

Now since we have enabled PARAMETERIZATION FORCED. Lets run both the select query and query the dm_exec_cached_plans to check the output.

select * from emp where emp_id = 1
go
select * from emp where emp_id = 700
go

select usecounts, cacheobjtype, objtype, [text]
from sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
where usecounts > 0
AND
[text] not like '%dm_exec_cached_plans%' and [text] not like  '%dm_exec_sql_text%'
order by usecounts desc
go   

usecounts cacheobjtype  objtype  text
--------  ------------- -------- --------------------------------------------
2         Compiled Plan Prepared (@0 int)SELECT * FROM emp WHERE emp_id=@0
1         Compiled Plan Adhoc    select * from emp where emp_id = 1
1         Compiled Plan Adhoc    select * from emp where emp_id = 700

Here we can see that no new Prepared plan gets generated, instead the same prepared plan is referred by the second query with emp_id = 700. And the data type chosen by SQL Server for constant is INT which satisfy both the constant.

Though you need to be careful while setting this
parameterization forced” since setting this option “on” for the database, you are letting SQL Server assume and treat all constant as a same parameter, which may give poor performance. Alternatives are available, which I will soon post as an article.

If my girl friend judge my love to code is like putting them in a strait jacket and kicking them down a flight, then yes.. I have deep love to my code K   

Post Reference: Vikram Aristocratic Elfin Share

Plan Caching V - Disadvantage of Simple Parameterization


Read Previous Post:

In   parameterization of Adhoc query (last article) we saw the a on the basis of constant it create parameterizated cached plan and store it in cache memory, but SQL Server makes its decision of the datatype of constant for example if you run this query after clearing cache and buffer

select * from emp where emp_id = 1
go

Then executing this sys.dm_exec_cached_plans query

select usecounts, cacheobjtype, objtype, [text]
from sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
where usecounts > 0
AND
[text] not like '%dm_exec_cached_plans%' and [text] not like  '%dm_exec_sql_text%'
order by usecounts desc
go

usecounts cacheobjtype  objtype  text
--------  ------------- -------- --------------------------------------------
1         Compiled Plan Prepared (@1 tinyint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 1

From the output we can see that the constant used in query where predict is being treated as tinyint. So the datatype is of the constant is being selected on fly by SQL Server while making a prepared Parameterized cache plan.

Now let’s query the same select with contact value ranging out of tiny data type.

select * from emp where emp_id = 700
go
  
Then executing this sys.dm_exec_cached_plans query

select usecounts, cacheobjtype, objtype, [text]
from sys.dm_exec_cached_plans
CROSS APPLY sys.dm_exec_sql_text(plan_handle)
where usecounts > 0
AND
[text] not like '%dm_exec_cached_plans%' and [text] not like  '%dm_exec_sql_text%'
order by usecounts desc
go

usecounts cacheobjtype  objtype  text
--------  ------------- -------- --------------------------------------------
1         Compiled Plan Prepared (@1 smallint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 700

Here we can see from the output that the constant is replaced by parameter and the type for the parameter is choosed as smallInt unlike tinyint in previous case.

Now here we will again execute the first query and will see whether this prepared query plan which is cached up in memory will get referred.

select * from emp where emp_id = 1
go

lets check  sys.dm_exec_cached_plans query now
usecounts cacheobjtype  objtype  text
--------  ------------- -------- --------------------------------------------
1         Compiled Plan Prepared (@1 smallint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 700
1         Compiled Plan Prepared (@1 tinyint)SELECT * FROM emp WHERE emp_id=@1
1         Compiled Plan Adhoc    select * from emp where emp_id = 1

So the output of the sys.dm_exec_cached_plans query shows two adhoc query and two prepared queries where one prepared query has parameter of type smallint and another has parameter type as tinyint.

Conclusion: Because of the nature of SQL Server to automatically choose the data type of constant in the query make a parameterized cache plan, we are not able to reuse the same plan though the nature of 2nd query is much similar to the first one.

So what is the option left.. Let’s check out in the next post same series ;)

Once my MBA friend pulled a knife on me. I asked her, the knife has butter on it, please don’t disturb, can’t u see I m writing code!!!… Why she is always angry with me…???


Post Reference: Vikram Aristocratic Elfin Share