Transaction关闭不当可能引发WinForm界面无反应的问题

来源:互联网 发布:天津武术培训知乎 编辑:程序博客网 时间:2024/05/16 06:20
在WinForm程序中,会对数据库进行一系列的操作。在一个Transaction中,在transaction.Begin()之后,因为try catch的逻辑有问题,在发生异常后,对于这个transaction既没有transaction.rollback(),也没有transaction.commit(). 这时候,有可能程序运行依然正常,但实际上是有问题的。因为这个transaction一直在占用着数据库中的某些表,锁住了某些表。之所以程序还能运行,是因为你目前的一些对于数据库的操作没有用到这些被锁住的表。一旦你再次操作被锁住的表,select,update等,都会出现pending的状态,就是一直在等表的释放。而这些锁是因为无意中的漏洞造成的,是不会释放的,所以,此时,就会出现WinForm的界面无反应问题。这里说的无反应不是说没有动静,而是该程序停留在卡住的状态。

对于Web应用,如果出现了上述transaction没有释放的问题,表现出来的还是比较明显的,在server中会抛出一个request timeout的异常。用户浏览器中也会有相关的信息。

这是一个经验问题,如果在做WinForm开发的时候,点击某个按钮或者其他的什么操作后,出现了界面无反应问题。可能是UI线程后台在进行耗时的操作,大量循环调用COM组件等,也或者是上边提到的数据库transaction没有关闭,这是很容易忽视的一点。所以,如果你的WinForm中有操作数据库,那么可以查看一下是否有这个问题。如何查看?我们可以在界面遇到问题后,到数据库中执行指定的SQL语句,查看当前所有的transaction,基本上如果是因为这个问题造成的,在这里就可以看到那些 没有关闭的transaction.

查看Transaction的SQL语句SELECT dt.transaction_id,       st.session_id,       database_transaction_begin_time,       CASE database_transaction_type         WHEN 1 THEN 'Read/write transaction'         WHEN 2 THEN 'Read-only transaction'         WHEN 3 THEN 'System transaction'       END database_transaction_type,       CASE database_transaction_state         WHEN 1 THEN 'The transaction has not been initialized.'         WHEN 3 THEN 'The transaction has been initialized but has not generated any log recorst.'         WHEN 4 THEN 'The transaction has generated log recorst.'         WHEN 5 THEN 'The transaction has been prepared.'         WHEN 10 THEN 'The transaction has been committed.'         WHEN 11 THEN 'The transaction has been rolled back.'         WHEN 12 THEN 'The transaction is being committed. not been materialized or persisted'       END database_transaction_state,       database_transaction_log_bytes_used,       database_transaction_log_bytes_reserved        FROM   sys.dm_tran_database_transactions dt       INNER JOIN sys.dm_tran_session_transactions st            ON st.transaction_id = dt.transaction_id

如果有的未关闭的transaction,结果应该类似下边的内容


如果想进一步查看transaction锁定了那些表,可以通过session_id进一步查询

select db_name(resource_database_id) 'DatabaseName',       object_name(resource_associated_entity_id) 'TableName',       request_type,       request_mode,       request_status from sys.dm_tran_locks where resource_type='OBJECT' and request_session_id=[进程ID]

PS: 关于如何查询block数据库的动作


原创粉丝点击