Showing posts with label trancount. Show all posts
Showing posts with label trancount. Show all posts

Saturday, February 11, 2012

@@Trancount Error

Take a look a the sql code below. Can anyone explain why @.@.trancount increased to 2 after the 2nd print statement?

SETANSI_DEFAULTSON

GO

PRINT@.@.TRANCOUNT

GO

BEGINTRANSACTION

PRINT@.@.TRANCOUNT

GO

Here is the output I got

0

2

With the ANSI_DEFAULTS you also enable IMPLICIT_TRANSACTIONS. So executing a BEGIN TRAN actually starts a second transaction because your implicit transaction is 'open' although it only returns 1 for @.@.TRANCOUNT when you actually issue a query.

WesleyB

Visit my SQL Server weblog @. http://dis4ea.blogspot.com

@@TRANCOUNT difference between SQL 7 and SQL 2000 in trigger

During testing of an application, i noticed a difference between
SQL 2000 and SQL 7, both with identical config.

In a nutshell:
A table has a trigger for UPDATE and DELETE.
When a column in the table is UPDATED the following happens:

In autocommit mode, when entering a trigger the trancount equals
1 for both SQL 7 and 2000.

When the same update is performed in an explicit transaction
in SQL 7 @.@.TRANCOUNT equal 2, and in SQL 2000 @.@.TRANCOUNT equals 1.

Configuration is the same and there are no implicit transactions.

I don't need a work around as this will invalidate the migration
process as both products should behave identically.
What would influence the difference or why is there a difference?
Is there something which has been overlooked?

================================================== =======

The following code replicates the problem

Ensure implicit transactions are off in both versions at the server
level, thus defaulting to autocommitted mode.
Ensure sp_configure settings are identical.

Step 1: Create a DB called test:

Step 2: Execute the following under the context of test DB.

if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[trigtest]') and OBJECTPROPERTY(id, Outrigger') = 1)

drop trigger [dbo].[trigtest]
GO

if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)

drop table [dbo].[test]
GO

if exists (select * from dbo.sysobjects where id =
object_id(N'[dbo].[trancount]') and OBJECTPROPERTY(id, N'IsUserTable')
= 1)

drop table [dbo].[trancount]
GO

CREATE TABLE [dbo].[test] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[text] [char] (10) NULL
) ON [PRIMARY]
GO

CREATE TABLE [dbo].[trancount] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[trancount] [int] NOT NULL
) ON [PRIMARY]
GO

CREATE TRIGGER trigtest ON [dbo].[test]
FOR UPDATE, DELETE
AS
declare @.trancount int

select @.trancount = @.@.TRANCOUNT

insert into trancount ( trancount ) values ( @.trancount )

Step 3: Run the following against the DB, then check trancount table.

-- Add a record to the test table (trigger will not fire)
insert into test (text) values ( 'xxxx' );
go

-- Update the value (autocommit mode) to fire trigger
-- Under SQL 7 and 2000, trancount table will only indicate 1
tranaction open.
-- This is being performed in autocommit mode.
update test set text = 'test1'
go

-- Update value using an explicit transaction
-- Under SQL 7, trancount will equal 2 in trigger, in SQL 2000
trancount equals 1
begin transaction
update test set text = 'test2'
commit work
goNeil Rutherford (neil_rutherford@.yahoo.com) writes:
> During testing of an application, i noticed a difference between
> SQL 2000 and SQL 7, both with identical config.
> In a nutshell:
> A table has a trigger for UPDATE and DELETE.
> When a column in the table is UPDATED the following happens:
> In autocommit mode, when entering a trigger the trancount equals
> 1 for both SQL 7 and 2000.
> When the same update is performed in an explicit transaction
> in SQL 7 @.@.TRANCOUNT equal 2, and in SQL 2000 @.@.TRANCOUNT equals 1.
> Configuration is the same and there are no implicit transactions.
> I don't need a work around as this will invalidate the migration
> process as both products should behave identically.
> What would influence the difference or why is there a difference?
> Is there something which has been overlooked?

Apparently there was - consciously or by chance - a change in SQL2000.
I cannot say why, and indeed 2 would be a more expected result in
this situation.

But I would be interesting to know why this would be an issue? It sounds
to me like your triggers must be doing something quite interesting.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp|||BOL says:
"Microsoft SQL Server 2000 increments the transaction count within a
statement only when the transaction count is 0 at the start of the
statement. In SQL Server version 7.0, the transaction count is always
incremented, regardless of the transaction count at the start of the
statement. This can cause the value returned by @.@.TRANCOUNT in triggers to
be lower in SQL Server 2000 than it is in SQL Server version 7.0.

In SQL Server 2000, if a COMMIT TRANSACTION or COMMIT WORK statement is
executed in a trigger, and there is no corresponding explicit or implicit
BEGIN TRANSACTION statement at the start of the trigger, users may see
different behavior than on SQL Server version 7.0. Placing COMMIT
TRANSACTION or COMMIT WORK statements in a trigger is not recommended."

HTH
Igor

neil_rutherford@.yahoo.com (Neil Rutherford) wrote in message news:<d6fdc377.0408070451.3d79fc95@.posting.google.com>...
> During testing of an application, i noticed a difference between
> SQL 2000 and SQL 7, both with identical config.
> In a nutshell:
> A table has a trigger for UPDATE and DELETE.
> When a column in the table is UPDATED the following happens:
> In autocommit mode, when entering a trigger the trancount equals
> 1 for both SQL 7 and 2000.
> When the same update is performed in an explicit transaction
> in SQL 7 @.@.TRANCOUNT equal 2, and in SQL 2000 @.@.TRANCOUNT equals 1.
> Configuration is the same and there are no implicit transactions.
> I don't need a work around as this will invalidate the migration
> process as both products should behave identically.
> What would influence the difference or why is there a difference?
> Is there something which has been overlooked?
> ================================================== =======
> The following code replicates the problem
> Ensure implicit transactions are off in both versions at the server
> level, thus defaulting to autocommitted mode.
> Ensure sp_configure settings are identical.
> Step 1: Create a DB called test:
> Step 2: Execute the following under the context of test DB.
> if exists (select * from dbo.sysobjects where id =
> object_id(N'[dbo].[trigtest]') and OBJECTPROPERTY(id, Outrigger') = 1)
> drop trigger [dbo].[trigtest]
> GO
> if exists (select * from dbo.sysobjects where id =
> object_id(N'[dbo].[test]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
> drop table [dbo].[test]
> GO
> if exists (select * from dbo.sysobjects where id =
> object_id(N'[dbo].[trancount]') and OBJECTPROPERTY(id, N'IsUserTable')
> = 1)
> drop table [dbo].[trancount]
> GO
> CREATE TABLE [dbo].[test] (
> [id] [int] IDENTITY (1, 1) NOT NULL ,
> [text] [char] (10) NULL
> ) ON [PRIMARY]
> GO
> CREATE TABLE [dbo].[trancount] (
> [id] [int] IDENTITY (1, 1) NOT NULL ,
> [trancount] [int] NOT NULL
> ) ON [PRIMARY]
> GO
> CREATE TRIGGER trigtest ON [dbo].[test]
> FOR UPDATE, DELETE
> AS
> declare @.trancount int
> select @.trancount = @.@.TRANCOUNT
> insert into trancount ( trancount ) values ( @.trancount )
>
> Step 3: Run the following against the DB, then check trancount table.
> -- Add a record to the test table (trigger will not fire)
> insert into test (text) values ( 'xxxx' );
> go
> -- Update the value (autocommit mode) to fire trigger
> -- Under SQL 7 and 2000, trancount table will only indicate 1
> tranaction open.
> -- This is being performed in autocommit mode.
> update test set text = 'test1'
> go
> -- Update value using an explicit transaction
> -- Under SQL 7, trancount will equal 2 in trigger, in SQL 2000
> trancount equals 1
> begin transaction
> update test set text = 'test2'
> commit work
> go|||Igor Raytsin (igorray@.yahoo.com) writes:
> BOL says:
> "Microsoft SQL Server 2000 increments the transaction count within a
> statement only when the transaction count is 0 at the start of the
> statement. In SQL Server version 7.0, the transaction count is always
> incremented, regardless of the transaction count at the start of the
> statement. This can cause the value returned by @.@.TRANCOUNT in triggers to
> be lower in SQL Server 2000 than it is in SQL Server version 7.0.
> In SQL Server 2000, if a COMMIT TRANSACTION or COMMIT WORK statement is
> executed in a trigger, and there is no corresponding explicit or implicit
> BEGIN TRANSACTION statement at the start of the trigger, users may see
> different behavior than on SQL Server version 7.0. Placing COMMIT
> TRANSACTION or COMMIT WORK statements in a trigger is not recommended."

It's even documented! I didn't know that. Thanks, Igor!

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp|||Thanks for your help guys.

Someone put logic in a trigger to only continue
if the @.@.TRANCOUNT came from an explicit transaction in
SQL Server 7 and the @.@.TRANCOUNT > 1

Like mentioned, in SQL 7 this works, but in SQL 2000..
it breached the integrity of a whole data warehouse system
test.

I have to convince the developers and management that
there is a change between versions. The developers
are convinced there is difference between the server
config and they believe that both versions should
work identically.

Unless I'm going blind.. where in books on-line is
the passage above?

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!|||Neil Rutherford (neil_rutherford@.yahoo.com) writes:
> Someone put logic in a trigger to only continue
> if the @.@.TRANCOUNT came from an explicit transaction in
> SQL Server 7 and the @.@.TRANCOUNT > 1

Dubious usage. I have not checked, but recursive trigger calls
may have slipped.

True, I have stored procedures which barf if you call them without
a transaction in progress, but that is because they perform only
half the job.

> I have to convince the developers and management that
> there is a change between versions. The developers
> are convinced there is difference between the server
> config and they believe that both versions should
> work identically.

Obviously there is a difference between versions. This is nothing you
configure.

> Unless I'm going blind.. where in books on-line is
> the passage above?

I searched for the string "the transaction count is always incremented"
and found two hits.

--
Erland Sommarskog, SQL Server MVP, esquel@.sommarskog.se

Books Online for SQL Server SP3 at
http://www.microsoft.com/sql/techin.../2000/books.asp

@@TRANCOUNT - always 0 or 1 ?..

I am trying to debug our production problem, and I'm stuck...

A C# .NET 1.1 method creates a SqlTransaction object on a SqlConnection. [This method is called from an ASP.NET 1.1 web application.]

The command invokes a stored procedure on SQL Server 2000 SP4 database.

The stored procedure itself is inside a transaction (that is, all batch code is between BEGIN TRANSACTION and COMMIT/ROLLBACK...).

DECLARE @.a_tran_count INT

SET @.a_tran_count = @.@.TRANCOUNT

DECLARE @.a_tran_name CHAR(13)

SET @.a_tran_name = CONVERT(CHAR(13), @.a_tran_count)

BEGIN TRANSACTION

DECLARE @.a_error INT

<Statements>

SET @.a_error = @.@.ERROR

IF 0 = @.a_error

<Statements>

SET @.a_error = @.@.ERROR

IF 0 = @.a_error

<Statements>

SET @.a_error = @.@.ERROR

IF @.@.TRANCOUNT > @.a_tran_count

BEGIN

IF 0 <> @.a_error

ROLLBACK TRANSACTION @.a_tran_name

COMMIT TRANSACTION

IF 0 = @.a_error

END

RETURN(@.a_error)

Apparently, there is an error in the last IF block (there should be ELSE just before COMMIT), and I don't like the error handling (it would be much more efficient to just rollback the transaction as soon as @.@.ERROR <> 0), but what I got stuck with is the following:

Is it possible that @.@.TRANCOUNT server variable will ever be other than 0 or 1?

I wrote some test page in C#, and it proved that SqlConnection indeed cannot support parallel transactions. But that's a .NET object, NOT a SQL Server's transaction...

I researched BOL and MSDN, but failed to find an answer to the question: if there can be only one transaction per one connection, then what's the point of using @.@.TRANCOUNT? So far, the only usage of it that I can imagine is for checking whether the current transaction has been started...

Also, using the @.a_tran_count (which is @.@.TRANCOUNT) to build the transaction name is kinda confusing as well... Is this name really needed in a procedure like this one?.. And what happens if there is another transaction running on this server which name is the same (such as "0")? Which transaction will be rolled back?

If the value of the @.@.TRANCOUNT can (at least, theoretically, - under certain rare circumstances) be greater than 1, it would mean I have found the cause of our current critical production issue and would be able to fix it relatively easily. So, any help would be greatly appreciated.

Thank you.

@.@.trancount is incremented by one for each "begin tran" and is decremented by one for each "commit":

if @.@.trancount > 0 rollback

begin tran

select @.@.trancount --1

begin tran

select @.@.trancount --2

commit

select @.@.trancount --1

commit

select @.@.trancount --0

It is set to zero when a "rollback" is issued:

if @.@.trancount > 0 rollback

begin tran

select @.@.trancount --1

begin tran

select @.@.trancount --2

rollback

select @.@.trancount --0

Because of the fact that a "rollback" sets the transaction count to zero, SQL Server is not usually considered to fully support "nested transactions".

Ron

|||as explained...@.@.trancount count does increase with each transaction added...rollback its it to zero just to add that... commit does @.@.trancount - 1...