1. 程式人生 > >SqlServer中巢狀事務使用--事務計數指示 BEGIN 和 COMMIT 語句的數目不匹配 --根本問題

SqlServer中巢狀事務使用--事務計數指示 BEGIN 和 COMMIT 語句的數目不匹配 --根本問題

問題:

1. System.Data.SqlClient.SqlException (0x80131904): EXECUTE 後的事務計數指示 BEGIN 和 COMMIT 語句的數目不匹配。上一計數 = 1,當前計數 = 0。

2. EXECUTE 後的事務計數指示 BEGIN 和 COMMIT 語句的數目不匹配。上一計數 = 0,當前計數 = 1。

後面的內容,是我之前寫的東西,主要是一些測試程式碼,但是呢,我沒有很深入的理解。現在直接說清楚本質的東西,把後面的精華再提上來說。 

  • 提交的事務不能撤銷或回滾。
  • 當不存在開啟的事務時,@@trancount 等於 0。
  • 執行 begin tran [tranName]語句將 @@trancount 增加 1。
  • 執行commit tran [tranName]語句將 @@trancount 減小 1。
  • 執行 rollback tran  會回滾整個事務並設定@@trancount 為 0。
  • 執行 " rollback tran  tranName"語句時有兩種情況:

if(tranName 之前 是用 " Save Tran tranName" 建立的 )  @@trancount值不變

否則,@trancount 減小1              

      注意:save tran 命令,不會使@@trancount加1

分析:

只要提交或者回滾事務後,程式內部改變了事務引數@@TRANCOUNT,就會出上述的錯誤,無一例外。

試圖直接用Sql "  set @@trancount = 1;",這是sqlserver 不允許做的。

各位,出現上面的錯誤,最多的可能是在巢狀事務中。

如果不巢狀:沒有begin tran前,@@trancount為0;  begin tran後,@@trancount  此時為1;完事後就commit或rollback@@trancount  此時為0;--不般我們是寫不錯的。

巢狀呢

    看看我之前寫的一個儲存過程:

[sql] view plaincopyprint?
  1. declare @trancount int --commit,rollback只控制本儲存過程
      
  2.     set @trancount = @@trancount;  
  3.     if (@trancount=0) /*判斷事務記數,根據情況確定使用儲存點或者新建一個事務*/   
  4.         begin tran current_tran--當前事務點,rollback、commit都從這裡開始    
  5.     else  
  6.         save tran current_tran  
declare @trancount int --commit,rollback只控制本儲存過程
    set @trancount = @@trancount;
    
	if (@trancount=0) /*判斷事務記數,根據情況確定使用儲存點或者新建一個事務*/ 
		begin tran current_tran--當前事務點,rollback、commit都從這裡開始 
	else
		save tran current_tran

.......

....做事去了

.......

[sql] view plaincopyprint?
  1. if @error_code != 0 or @logErrorCode != 1  
  2.         begin  
  3.             rollback tran current_tran  
  4.             set @error_code = -1; -- 失敗   
  5.         end  
  6.     else  
  7.         begin  
  8.             commit tran current_tran  
  9.             set @error_code = 1; -- 成功   
  10.          end  
if @error_code != 0 or @logErrorCode != 1
		begin
			rollback tran current_tran
			set @error_code = -1; -- 失敗
		end
	else
		begin
			commit tran current_tran
			set @error_code = 1; -- 成功
		 end

有沒有問題?(current_tran是儲存點哈,不明白的,後面有比較詳細的介紹)

我用了好久了(在一個專案裡面),可是突然有一天,也就是今天,它出事了。原因嘛,雖然寫的是巢狀的,之前都沒有巢狀調到過。

我在外圍開了一個事務,再來調這個儲存過程,當它 commit tran current_tran 時(rollback tran current_tran是不會有事的),會出什麼錯誤?如果你不能很明確的告訴我,說明你還沒有理解得深刻。做個選擇吧?

1."...BEGIN 和 COMMIT 語句的數目不匹配。上一計數 = 0,當前計數 = 1。"

2."...BEGIN 和 COMMIT 語句的數目不匹配。上一計數 = 1,當前計數 = 0。

答案:【2】。

線索分析:我是在外部開了一個事務的,所以在未進入該儲存過程以前@@trancount的值應該為1;進入時,save tran current_tran, @@trancount值沒有變;完事的,執行commit tran current_tran,@@trancount的值應該為0;--所以,進入前,出來後,@@trancount值發生了改變,SqlServer不幹了(原因,自己去想吧:拆散了begin tran 配對)。

怎麼解決

 1.進入子事務前先記錄@@trancount,我們用變數@trancount來記錄。

 2. 提交子事務前,先判斷之前的@trancount是否為0;為0表示"該事務"前沒有事務呼叫,可以直接提交事務;不為0,表明進入該事務前已經有一個事務,該事務是子事務,不能提交。

[sql] view plaincopyprint?
  1. -- 如果當前計數為0,則提交.    
  2.          -- 因為Commit tran ,@@TRANCOUNT會減1。巢狀事務時,呼叫該存在過程(作為子過程,此時@@TRANCOUNT > 0),   
  3.          -- 只是儲存了tran, @@TRANCOUNT沒有發生改變;直接Commit會使@@TRANCOUNT減1,會打破事務對(Begin Tran)   
  4.         if(@trancount = 0)  
  5.         begin  
  6.             commit tran current_tran  
  7.         end  
  8.         set @error_code = 1; -- 成功  
 -- 如果當前計數為0,則提交. 
			 -- 因為Commit tran ,@@TRANCOUNT會減1。巢狀事務時,呼叫該存在過程(作為子過程,此時@@TRANCOUNT > 0),
			 -- 只是儲存了tran, @@TRANCOUNT沒有發生改變;直接Commit會使@@TRANCOUNT減1,會打破事務對(Begin Tran)
			if(@trancount = 0)
			begin
			    commit tran current_tran
			end
			set @error_code = 1; -- 成功

SqlServer 事務相關:《巢狀事務(一):.NET中巢狀事務運用的一點思考》

相關推薦

SqlServer事務使用--事務計數指示 BEGIN COMMIT 語句數目匹配 根本問題

問題: 1. System.Data.SqlClient.SqlException (0x80131904): EXECUTE 後的事務計數指示 BEGIN 和 COMMIT 語句的數目不匹配。上一計數 = 1,當前計數 = 0。 2. EXECUTE 後的事務計數指示 B

Android-ListView(ListView)控制元件時item的點選事件起作用的問題

解決:1、在主listview佈局檔案中的listview中新增屬性 android:focusable="false"              2、在子listview中最頂上的佈局檔案新增屬性

sql server事務*

轉自 https://www.cnblogs.com/guanjie20/archive/2013/02/17/2914488.html 我們在寫事務時經常遇到的問題如下: 訊息 266,級別 16,狀態 2,過程 sp1,第 0 行 EXECUTE 後的事務計數指示&nb

iview框架遇到在modalmodal

在iview中modal的z-index是一樣的,都是1000,但是很多時候需要在modal1的上面彈出modal2,這時需要對modal新增一個class-name,然後對這個class新增屬性值{z-index:1002},這時解決了modal2顯示在modal1上,可是modal2的mask(

NavigationView headerLayoutRecyclerView滑動衝突問題

<?xml version="1.0" encoding="utf-8"?> <com.vechain.vecar.ui.view.MyDrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"

Vue私有元件註冊的問題(元件元件)

我們先宣告兩個元件物件 let a-component={ template:` <h1> A元件 </h1> ` } let b-component={ template:` <h1> B元件 <

Vue的 slot插槽的簡單應用——input按鈕的效果

場景: 需要一種類似於把按鈕放在input最右邊的效果 解決辦法: 1,發現在Vue中怎麼巢狀都出不了效果,網上搜到的一種html寫法(但是和Vue中的el-table-column有些影響): <form role="form"> <div cla

NestedScrollViewListview後只顯示一個item

出現這種情況的原因是Listview能識別NestedScrollView的高度。 解決辦法是新建一個MyListView繼承ListView然後重寫其中的onMeasure方法 具體實現: public class MyListView extends ListView {

Asp.net MVC訪問母版頁的iframe頁面時,如果session或cookie過期,登入驗證超時怎樣自動跳轉到登入頁

一般登入驗證的過濾器中,使用驗證過濾器的Redirect方法,將請求重定向到指定的URL。但是如果我們要訪問的頁面是一個巢狀在母版頁中的iframe頁面時,這種重定向只會對iframe頁面湊效,也就是會將iframe也重定向到登入頁,這樣就有違我們的目的了。所以我就嘗試了很多方法來實現讓整個頁面重定向到登入頁

在小程式h5頁面,點選事件觸發

最近在寫小程式,由於小程式快滿了,就把頁面寫成h5,嵌在小程式裡,原以為很簡單,沒想到遇到問題,問題不多,但是很大 第一個就是點選事件不觸發, 場景如下:     點選按鈕觸發ajax請求,請求成功之後跳轉到另一個頁面,但是頁面始終不跳轉。 解決方法,將http開

解決scrollView編輯框導致能上下滑動的問題

EditText設定maxLines之後,文字行數超過maxLines,會網上摺疊,上下滑動能夠瀏覽全部文字。 若EditText外層有scrollView。在EditText上下滑動,不會像正常情況那樣上。僅僅會滑動了scrollView。 解決的方法是:

EL表示式EL表示式解決方法

1.模擬需求:從一個商品集合中取出所有商品,第一個商品用它的第一張圖片,第二個商品用它的第二張圖片 2.起初按照通用思路,在c:forEach中定義一個varStatus,再通過vaStatus獲取下標,結果寫成了el表示式巢狀(如下),結果根本出不來 <c:forEach it

vue頁面 iframe 標籤

vue中巢狀iframe,將要巢狀的檔案放在static下面:   <iframe src="../../../static/bear.html" width="300" height="300" frameborder="0" scrolling="auto"></ifr

webviewhtml實現精準定位(百度地圖、高德地圖、騰訊地圖、H5原生定位)js對比

最近在實現一個功能,就是在安卓手機和蘋果手機嵌入html程式碼,實現精準定位,我為此對比幾種定位的方法。我要的是精準定位,就是誤差在100米左右的功能,類似與外賣app那種定位精確度 1. 首先是原生h5定位 if(browser.versions.an

iview之——tableinput、select等

使用iview在table中嵌入button是比較常見的需求,但是在table中嵌入input或者select你是否考慮過呢?本文用例項介紹input和select在table中的巢狀。 理解table如何巢狀input、select首先要理解vue的render函式可以參考:vue render函式介紹。當

【Rails】PostgreSQLjson查詢

備忘:工作記錄。 # attr_json:{"ext": {"conditions": {"appId": "168","templateSettings": {"is_show": true,"

陣列物件,根據物件的某個字對物件進行去重

// 陣列中巢狀物件,根據物件的某個欄位進行物件去重 function uniqObj(data, name) { var dataArr = []; var dataObj = {}; for (var i = 0; i < data.length; i+

【EL 表示式】EL 表示式 EL 表示式

需求 需要從一個文章集合中根據不同的標籤取出文章,第一篇文章用第一個標籤,第二篇文章用第二個標籤 原有思路 <c:forEach items="${articles}" var="article" varStatus="ids"> <img

根據影象名字把一個大資料夾影象分類(matlabfor迴圈if語句

clear; close all; clc; inpath = 'G:\code\xianzhu\Z_CODE\SalBenchmark-master\Data\DataSet1\Saliency\*.png'; %%需要分類的資料夾路徑 %%分類後圖像儲存路徑%% CA_p

Android應用的LinearLayoutRelativeLayout的佈局用法

想將Button和ListView分別放在螢幕的一左一右。 單純使用android:gravity和android:layout_gravity不成功。 於是涉及到RelativeLayout。 關鍵為:android:layout_alignParentRight="tr