T-SQL错误3930
(2010-10-04 01:35:10)
下一个
一大早遇上个问题:帮其他TEAM开发的一个SP,运行出错。报的错误信息是:
メッセージ 3930、レベル 16、状態 1、行 xx 。現在のトランザクションのコミットおよびログ ファイルに書き込む操作は サポートできません。(The current transaction cannot be committed and cannot support operations that write to the log file.)
原本已经调试通过的程序,代码应该不会有问题。一查出错的行数,那一行代码居然是:COMMIT TRANSACTION,很稀罕的错误。再一检查运行的环境,只有登陆的用户名与开发、调试时使用的不同,初步估计与用户权限设定有关。
网上与error3930有关的信息很少,微软的联机帮助也语焉不详。好不容易查到一篇文档,说报这个错时,XACT_STATE()的值一定是-1(正常时为1)。
再查XACT_STATE()的帮助文档,发现一条有价值的说明,这个error与try...catch有关。这时猛想起程序中调用一个共通的函数,是别的TEAM以前开发的、沿用至今。这个共通函数又调用其他的子函数,多层嵌套的调用,业务逻辑很复杂,从没花过气力去研究它,但依稀记得其中正是用了很多的try...catch。
再查try...catch的帮助文档,果然其中有关于COMMIT不能的情形的说明。当try的过程当中发生了事务不得不中止的情况时,事务就变成了不能COMMIT的状态。本来这可能会引起程序Abort,但由于catch的存在,程序跳转到catch部分处理,而catch部分只是设置了错误信息、然后返回,并没有进一步抛出例外、引起主程序的异常中止,使得主程序按照正常处理、执行到COMMIT,从而引起了3930错误。
按照以上的理解,用定位XACT_STATE()值变成-1的时间点的办法进行排错,很快找到了隐藏在几层子函数调用下的问题点:对某一个其他DB里的被查询的表,没有足够的访问权限。
メッセージ 916、レベル 14、状態 1、行 1
現在のセキュリティ コンテキストでは、サーバー プリンシパル "XXX" はデータベース "XXX" にアクセスできません。
这个916错误,才是被catch给“吃掉”了的真正的错误信息。