Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 Help with TRANSACTIONS :-(

Author  Topic 

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 10:07:48
Hello,
I have been reading up on transactions and trying to see how they work.

PROBLEM
we have a table that does billing for clients. Which basically works as thus:

1. check user credits and assign to a variable
2. Check users total bill
3. Update credits table

However, between 1 ( read column) and 3 (update column)...

I noticed that if another sql statement hits that column before. It changes the value.

How can we make sure that once a user starts to be billed another transaction cant update it until its finished ?

thanks






1st QUERY: BILLING TRANSACTION
DECLARE @TranName VARCHAR(20)
SELECT @TranName = 'MyTransaction'

BEGIN TRANSACTION @TranName

select * from moneytable where username = 'sally'

WAITFOR DELAY '00:00:10';-- Create an artificial delay while query 2 runs

update moneytable set credits = 10 where username = 'sally'

commit transaction MyTransaction



2nd QUERY
update moneytable set credits = '0' where username = 'sally'























_____________________


Yes O !

bjoerns
Posting Yak Master

154 Posts

Posted - 2008-09-12 : 10:25:29
Does it update within the 10 seconds or afterwards?
If within, how did you find out?
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2008-09-12 : 10:31:43
Transaction Isolation Level is what you need to SET to change the affects concurrency. My guess is you will want to set it to REPEATABLE READ. But you should read about it on Books Online.

Be One with the Optimizer
TG
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 10:49:59
quote:
Originally posted by bjoerns

Does it update within the 10 seconds or afterwards?
If within, how did you find out?



2 Ways to find out

1. I opened the table in Management studio and while the delay time of 2mins (in the transaction) is pending, I run query 2

2. the end value is the value of query 2 which is different from query 1 ( which is the transaction )



_____________________


Yes O !
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 10:52:27
quote:
Originally posted by TG

Transaction Isolation Level is what you need to SET to change the affects concurrency. My guess is you will want to set it to REPEATABLE READ. But you should read about it on Books Online.

Be One with the Optimizer
TG



I posted a thread here about locks and isolation level. But was adviced not to use them as SQL server automatically sets them

See
http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=110308

quote:
Originally posted by Bustaz Kool

The SQL engine will assign the lock that it thinks is the most appropriate based on efficiency and the current activity. You don't assign a lock and, by and large, you don't need to worry about it. You can influence the SQL engine by using a lock hint (e.g., ROWLOCK) but this does not force the lock.

If you are doing a single UPDATE statement, you don't need to worry about locks at all. The SQL engine treats that as an atomic event and so won't let anyone else change a value in the row while you are performing your update.

Does that answer your question?

=======================================
It is impossible to imagine Goethe or Beethoven being good at billiards or golf. -H.L. Mencken, writer, editor, and critic (1880-1956)



quote:
Originally posted by TG

Already wrote this when I saw Bustaz Kool's post - but I'll post anyway :)

The default transaction isolation level "read committed" is usually sufficient without using any explicit locking hints. Especially if you are using stored procedures where the update is virtually instantaneous (as opposed to holding the row locked from an application during user interaction). Are you experiencing any blocking problems?

Be One with the Optimizer
TG



_____________________


Yes O !
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2008-09-12 : 11:20:17
Your original question in that other thread did not lay out this scenario. Actually, your scenario was described ust as "--MY CODES GO HERE". Once you elaborated (slightly) I said that we didn't have enough info to answer your question. You never responded with the info I asked for. Now this thread is asking a different question than your elaboration from the other thread. Given your example (above) I say you DO need to change the isolation level from the default behavior.

If you're interested I can post an example test for the scenario above illustrating how isolation level can change the concurrency behavior (for that specific scenario).

Be One with the Optimizer
TG
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 11:26:11
quote:
Originally posted by TG


If you're interested I can post an example test for the scenario above illustrating how isolation level can change the concurrency behavior (for that specific scenario).

Be One with the Optimizer
TG



Oh, am sorry about that.

Yes pls post an example, i would appreciate that.
Thanks

_____________________


Yes O !
Go to Top of Page

bjoerns
Posting Yak Master

154 Posts

Posted - 2008-09-12 : 12:00:34
Well of course the end value is value of query 2. The update waits nicely for the select to return, then does its job?!
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 12:08:16
Yes, but I need help on how to get this transaction working.

So that the user is billed appropriately

_____________________


Yes O !
Go to Top of Page

bjoerns
Posting Yak Master

154 Posts

Posted - 2008-09-12 : 12:13:40
quote:
1. check user credits and assign to a variable
2. Check users total bill
3. Update credits table

However, between 1 ( read column) and 3 (update column)...

I noticed that if another sql statement hits that column before. It changes the value.


If steps 1 - 3 are enclosed in a transaction, it changes the value afterwards. Isn't that the expected behaviour?
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2008-09-12 : 12:18:36
With no locking hints or changes to trans isol level the other session is not blocked from updating the value.
Here is an example:
Run this 4 times:
1. as is (while waitfor is waiting run the 2nd query in another window)
2. leave default isol lev but UNCOMMENT locking hint on assignment of @credits "--with (updlock)"
3. re-comment the locking hint. use SERIALIZABLE TransIsolLev
4. use Repeatable Read TransIsolLev


set nocount on
use tempdb

create table moneytable (username varchar(10), credits int)
insert moneytable values ('sally', 1)

set transaction isolation level read committed --DEFAULT SETTING
--set transaction isolation level serializable
--set transaction isolation level repeatable read


declare @credits int
,@msg varchar(50)

print 'begin transaction'
BEGIN TRANSACTION

select @credits = credits
from moneytable --with (updlock)
where username = 'sally'

print 'before waitfor (in transacation)'
select @credits [@credits]

WAITFOR DELAY '00:00:05'

update moneytable set credits = 3 where username = 'sally'

commit transaction

print 'after transaction'
select * from moneytable


/*
--2nd QUERY RUN THIS in another window while WAITFOR is running
update moneytable set credits = '0' where username = 'sally'
*/

go
drop table moneytable

/*
---------------------------------------------------------------
CASE 1:
transaction isolation level read committed --default
no locking hint

Result:
no blocking
no deadlock
2nd query ran between 2 statements in the transaction.
Final Credits value: 3

---------------------------------------------------------------
CASE 2:
transaction isolation level read committed --default
Variable Read with UPDLOCK locking hint

Result:
blocking
no deadlock
2nd query ran AFTER 2 statements in the transaction
Final Credits value: 0 (from 2nd window)
---------------------------------------------------------------
CASE 3:
transaction isolation level Serializable
no locking hint

Result:
blocking
no deadlock
2nd query ran AFTER 2 statements in the transaction
Final Credits value: 0 (from 2nd window)

---------------------------------------------------------------
CASE 4:
transaction isolation level Repeatable Read
no locking hint

Result:
blocking
DEADLOCK - 2nd query Deadlocked and terminated as deadlock victim
Final Credits value: 3
---------------------------------------------------------------
*/


EDIT:
added red
Be One with the Optimizer
TG
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 13:06:05
Ok thank you. will try it out.

brb

_____________________


Yes O !
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 13:14:36
Sorry TG, but it doesnt work.

when i run two open windows, the first window has your query and the second window has this

use [delete]
update moneytable set credits = -100 where username = 'sally'

select * from moneytable


I changed the delay time to
WAITFOR DELAY '00:00:20'

When i run your query, and then while the delay waits. I run the 2nd, and the results i get is

username credits
sally -97

_____________________


Yes O !
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2008-09-12 : 13:23:41
Well, you've got different code than I did since you ended up with -97 ???

what do you mean "it doesn't work"?
The whole purpose was to compare the 4 different scenarios:
1. read committed
3. serializable
4. repeatable read
2. read committed and "with (updlock)" on the first read

Did all four return the same results?

Be One with the Optimizer
TG
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 13:26:58
One min pls

_____________________


Yes O !
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 13:31:30
Ok the
set transaction isolation level serializable

Does it for me. But one question about the isolation levels.

From the last thread. I understand that the isolation level is already set. Does this instruction "RESET" the isolation level,and after the query has finished what will the isolation level be ?

2. does it affect the database when i set an isolation level ?
thanks

_____________________


Yes O !
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2008-09-12 : 13:45:10
The SET command affects the current session including any/all statements after the SET command. For as long as that session is active the isolation level will be the last value it was SET to. (if it was never set than the default level is read committed)

>>does it affect the database when i set an isolation level ?
Of course, but just for the session that set it. It is not a "global" setting that affects other processes unless they are attempting to concurrently access the same resources affected by the session that SET it.

I believe 2 options satisfied your objective:

2. read committed and "with (updlock)" on the first read
3. serializable

Though the affect for this test is identical between these 2 options, I think the (updlock) locking hint may be a less "aggressive" solution.

Be One with the Optimizer
TG
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 15:18:22
Quite educative.

Thanks a lot.

One last question, How do i check the default isolation ? and after running my query, i can use the same command to set it back to the default ???

_____________________


Yes O !
Go to Top of Page

TG
Master Smack Fu Yak Hacker

6065 Posts

Posted - 2008-09-12 : 15:31:58
You can't set it to "default" but you can set it back to what you know the default is "read committed" by using the same SET command.

You can View the current isolation level by using:
dbcc useroptions
However, unless you explicitly set the value to something other than default, "isolation level" won't appear in the results.


Be One with the Optimizer
TG
Go to Top of Page

afrika
Master Smack Fu Yak Hacker

2706 Posts

Posted - 2008-09-12 : 15:37:52
Are there any side effects to isolation locks, as they "MUST" use a lot of memory ? and have downsides
Go to Top of Page

mary_itohan
Posting Yak Master

191 Posts

Posted - 2008-09-12 : 15:39:37
quote:
Originally posted by TG

You can't set it to "default" but you can set it back to what you know the default is "read committed" by using the same SET command.

You can View the current isolation level by using:
dbcc useroptions
However, unless you explicitly set the value to something other than default, "isolation level" won't appear in the results.


Be One with the Optimizer
TG



Thanks TG

_____________________


Yes O !
Go to Top of Page
    Next Page

- Advertisement -