In our application, there's a database update that is committed only after a consequent update is being executed (both using the same transaction, of course). However, we've discovered a rar开发者_JAVA百科e flow in which the user exits the application before the second update, causing the first to be discarded. I'm looking for a way to recognize this uncommitted update upon exit.
I know problems like this call for redesign, but that not possible. Due to the rarity of the flow and the structure of the app, I'm wondering if there's a way to just check the transaction itself for uncommitted updates.
Question is valid for Oracle and SQLServer. The app is written in PowerBuilder, but it can be extended in various ways (.NET, Win32 etc.) if that matters.
In Oracle you can call DBMS_TRANSACTION.local_transaction_id. This will either return a unique identifier of the current transaction, or NULL if no transaction is active.
Share and enjoy.
This might be helpful
@@TRANCOUNT (Transact-SQL)
Returns the number of active transactions for the current connection.
If you're on PB11.5 and use a custom transaction object, it's pretty easy to do something that isn't DBMS-dependent. In the SQLPreview event of the transaction object, simply toggle a boolean on when an INSERT, UPDATE or DELETE goes by, then toggle it off when a COMMIT or ROLLBACK goes by.
Actually, it's not that hard to swap in a custom transaction object if you're using SQLCA: Application, Properties, Additional Properties, Variable Types, SQLCA. If you're using a lot of separate database connections with a lot of "CREATE transaction" statements (standard PB search can find this, or PBL Peeper can help you find this with variable number of spaces between the words), then implementing this will be harder, but not impossible.
And, for the sake of completeness, to create a custom transaction object, File / New / PB Object / Standard Class / Transaction. You've got a regular user object where you can define Instance Variables (like the boolean I've suggested) and script events (like the SQLPreview event I've suggested) and functions (you may want to create an interface for this functionality to hide the details in case you want to extend it in the future). Note that SQLPreview isn't available on the Transaction object before 11.5. (For those that think it sounds familiar before 11.5, the DataWindow implements a SQLPreview.)
Good luck,
Terry.
In Oracle there is a view V$TRANSACTION
which contains a row for each uncommitted transaction. There is no mechanism for seeing the nature of that transaction from outside (unless you have instrumentation built into your code, e.g. by using DBMS_APPLICATION_INFO.SET_MODULE()
). However, the current session could see whether it has uncommitted work like this:
SQL> select t.status
2 from v$transaction t
3 join v$session s
4 on s.saddr = t.ses_addr
5 where s.sid = sys_context('userenv', 'sid')
6 /
STATUS
----------------
ACTIVE
SQL>
If there are no uncommitted transactions then this query will return NO_DATA_FOUND. The V$ views are not granted to users by default, as they are really a DBA thang. However, a user with the appropriate privilege can turn this query into a view and grant access to the regular joes.
As a matter of interest, what would you want to do, anyway? Presuming the Unit Of Work is correctly defined ad two updates, surely it would be wrong to commit just the one. If all you want to know is that this abnormal termination occurred then some form of trace or logging is what you need.
edit
Bob Jarvis proposes using DBMS_TRANSACTION.LOCAL_TRANSACTION_ID()
. That is a better suggestion than a handcrafted view. The V$TRANSACTION view can also be used to monitor uncommitted transactions from other sessions.
In order to facilitate the troubleshooting of your scenario you may wish to consider the use of explicit named local transactions, along with the use of the “WITH MARK” option. This permits you to record the name of an explicit transaction to the transaction log, which you can of course inspect at a later stage in order to identify the sequence of events that has occurred.
See SQL Server Books Online: Marked Transactions
In SQL Server, run this:
IF @@TRANCOUNT>0 BEGIN
ROLLBACK;
END;
In SQL Server 2005/2008, you can use the DMV. Check out this article
精彩评论