![]() | |
![]() |
| | Thread Tools | Display Modes |
#1
| |||
| |||
|
#2
| |||
| |||
|
|
1, Process A sets isolation level to snapshot 2, Process A starts new transaction by setting autocommit to off 3, Process A inserts a record in db 4, process A commits (sqlEndTran(commit)) 5, process A signals via ipc to process B, sending the key of this record 6, Process B sets isolation level to snapshot 7, Process B starts new transaction by setting autocommit to off 8, Process B selects on the table, with the given key as where clause 9, Process B get no hit. record is not found Looking with sqlcmd in db, the record IS there |
#3
| |||||
| |||||
|
|
björn lundin (b.f.lun... (AT) gmail (DOT) com) writes: 1, Process A sets isolation level to snapshot 2, Process A starts new transaction by setting autocommit to off 3, Process A inserts a record in db 4, process A commits (sqlEndTran(commit)) 5, process A signals via ipc to process B, sending the key of this record 6, Process B sets isolation level to snapshot 7, Process B starts new transaction by setting autocommit to off 8, Process B selects on the table, with the given key as where clause 9, Process B get no hit. record is not found Looking with sqlcmd in db, the record IS there Note that in SQL Server there is no such thing as "SET AUTOCOMMIT OFF". There is only BEGIN TRANSACTION. |
|
It sounds from your description that B already has a transaction in progress, possibly orphaned. |
|
Rather than using true snapshot isolation, you could consider setting the database in READ_COMMITTED_SNAPSHOT. In this case, the default isolation level READ COMMITTED will be implemented through the snaphot. |
|
In this, you don't need to start to explicit transactions to use the snapshot and avoid that readers and writers block each other. |
|
Particularly, in this situation, even if B has an orphaned transaction, it will still see the row inserted by A, because it reads committed data. |
#4
| ||||||
| ||||||
|
|
Is there a way to query the db or ODBC-driver whether I'm already in a transaction or not? |
|
As I understand the quoted text above, there is no Start_Transaction. The first statement after a commit/rollback actually starts the transaction. |
|
begin Start_Transaction(T) Prepare(S1,"SELECT cola,colb,colc FROM foo WHERE bar=:bar"); Prepare(S2,"UPDATE foo2 SET colb = 10 WHERE colb = :B); Set(S1,"bar",25); Open_Cursor(S1) Cursor_Loop loop Fetch(S1,End_Of_Set) exit Cursor_Loop when End_Of_Set; Get(S1,"colb",B); if is_odd(B) then Set(S2,"colb",B); Execute(S2) -- <== may raise Transaction_Conflict end if; end loop Cursor_Loop; Close_Cursor(S1); Commit(T) -- A successful commit means leave the loop exit Transaction_Loop; exception when Transaction_Conflict => -- start all over again Close_Cursor(S1); Rollback(T); end Transaction_Loop; |
|
That implicates that 2 consecutive selects with the same conditions may return different resultsets, depending on insert/delete/updates made by others between the selects. |
|
This READ_COMMITTED_SNAPSHOT, when I set it, does it apply to all coming sessions in the database? |
|
Now this is something I'd like to fix. How do I track down orphaned transactions. Having them points to error in my code, and that, I do not want... When i look in the management Studio, looking at database report 'All transactions' I get the reply that there are no current transactions... |
#5
| ||||||
| ||||||
|
|
björn lundin (b.f.lun... (AT) gmail (DOT) com) writes: Is there a way to query the db or ODBC-driver whether I'm already in a transaction or not? "SELECT @@trancount" returns your current level of transaction nested. Any number >= 1 means that you have a transaction in progress. |
|
There is a command, SET IMPLICIT_TRANSACTION ON. When this setting is in effect, the first command that performs an update will start a transaction. This setting is off by default, which is different from other product where implicit transactions is the norm. Implicit transactions is also what ANSI mandates. |
|
Personally, I don't like what is being is said in the ODBC manual. I much rather submit BEGIN/COMMIT/ROLLBACK TRANSACTION commands myself than have the API to perform things behind my back. |
|
I don't know exactly what this code is doing, but it seems to me that it could be implemented with a single UPDATE statement for better performance and less risk for deadlocks. |
|
This Â*READ_COMMITTED_SNAPSHOT, when I set it, does it apply to all coming sessions in the database? All sessions that use the READ COMMITTED isolation level. |
|
I get the reply that there are no current transactions... Once your application exists, all these transactions will of course be rolled back. |
#6
| ||||
| ||||
|
|
Well yes. But I put the code there to illustrate some requirements that I have * MARS, or multiple active record sets. It is used a lot. |
|
* The statements are prepared, and late on bound. |
|
But in reality, there were 3 more steps -1, Process A sets isolation level to snapshot 0 , Process A starts new transaction by setting autocommit to off 5.5 process A commits (sqlEndTran(commit)) |
|
However, it all worked in READ_COMMITTED mode, which implies on of two things * Process B got a dirty read * The Snapshot handling is so much slower that Process B was too quick reading, so Process A had not yet done its final commit. And when not using snapshot, process A send the IPC, and committed, BEFORE Process A got to read. I prefer to believe its the second option, but will keep my eyes on it until I know for sure. |
#7
| ||||
| ||||
|
|
björn lundin (b.f.lun... (AT) gmail (DOT) com) writes: Well yes. But I put the code there to illustrate some requirements that I have * MARS, or multiple active record sets. It is used a lot. Ugh! I can't say that MARS is anything I recommend. When used correctly, it is not likely to be harmful, but it can lure you do things you should not do. |
|
Still a stored procedure that performs all the business logic will more efficient that sending data forth and back between server and client.. |
|
Not really. But without snapshot, B was blocked until A had performed its final commit, whereas with snapshot B just reads the old data. No scheme is perfect, and with snapshot - either true snapshot isolation or read_commited_snapshot - the risk is that you read stale data. |
|
If you have situtaions where a process may be signaled about new data that has not yet been committed, that process cannot use snapshot isolation to read the data. This is the one situation where enabling RCSI can wreak havoc on an application. You can use the hint (READCOMMITTEDLOCK) to prevent this from happening. |
![]() |
| Thread Tools | |
| Display Modes | |
| |