<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    隨筆-348  評論-598  文章-0  trackbacks-0

      數(shù)據(jù)庫事務(wù)是指作為單個邏輯工作單元執(zhí)行的一系列操作。

    設(shè)想網(wǎng)上購物的一次交易,其付款過程至少包括以下幾步數(shù)據(jù)庫操作:

      · 更新客戶所購商品的庫存信息

      · 保存客戶付款信息--可能包括與銀行系統(tǒng)的交互

      · 生成訂單并且保存到數(shù)據(jù)庫中

      · 更新用戶相關(guān)信息,例如購物數(shù)量等等

    正常的情況下,這些操作將順利進行,最終交易成功,與交易相關(guān)的所有數(shù)據(jù)庫信息也成功地更新。但是,如果在這一系列過程中任何一個環(huán)節(jié)出了差錯,例如在更新商品庫存信息時發(fā)生異常、該顧客銀行帳戶存款不足等,都將導(dǎo)致交易失敗。一旦交易失敗,數(shù)據(jù)庫中所有信息都必須保持交易前的狀態(tài)不變,比如最后一步更新用戶信息時失敗而導(dǎo)致交易失敗,那么必須保證這筆失敗的交易不影響數(shù)據(jù)庫的狀態(tài)--庫存信息沒有被更新、用戶也沒有付款,訂單也沒有生成。否則,數(shù)據(jù)庫的信息將會一片混亂而不可預(yù)測。

    數(shù)據(jù)庫事務(wù)正是用來保證這種情況下交易的平穩(wěn)性和可預(yù)測性的技術(shù)。

      數(shù)據(jù)庫事務(wù)的ACID屬性

    事務(wù)處理可以確保除非事務(wù)性單元內(nèi)的所有操作都成功完成,否則不會永久更新面向數(shù)據(jù)的資源。通過將一組相關(guān)操作組合為一個要么全部成功要么全部失敗的單元,可以簡化錯誤恢復(fù)并使應(yīng)用程序更加可靠。一個邏輯工作單元要成為事務(wù),必須滿足所謂的ACID(原子性、一致性、隔離性和持久性)屬性:

      · 原子性

    事務(wù)必須是原子工作單元;對于其數(shù)據(jù)修改,要么全都執(zhí)行,要么全都不執(zhí)行。通常,與某個事務(wù)關(guān)聯(lián)的操作具有共同的目標(biāo),并且是相互依賴的。如果系統(tǒng)只執(zhí)行這些操作的一個子集,則可能會破壞事務(wù)的總體目標(biāo)。原子性消除了系統(tǒng)處理操作子集的可能性。

      · 一致性

    事務(wù)在完成時,必須使所有的數(shù)據(jù)都保持一致狀態(tài)。在相關(guān)數(shù)據(jù)庫中,所有規(guī)則都必須應(yīng)用于事務(wù)的修改,以保持所有數(shù)據(jù)的完整性。事務(wù)結(jié)束時,所有的內(nèi)部數(shù)據(jù)結(jié)構(gòu)(如 B 樹索引或雙向鏈表)都必須是正確的。某些維護一致性的責(zé)任由應(yīng)用程序開發(fā)人員承擔(dān),他們必須確保應(yīng)用程序已強制所有已知的完整性約束。例如,當(dāng)開發(fā)用于轉(zhuǎn)帳的應(yīng)用程序時,應(yīng)避免在轉(zhuǎn)帳過程中任意移動小數(shù)點。

      · 隔離性

    由并發(fā)事務(wù)所作的修改必須與任何其它并發(fā)事務(wù)所作的修改隔離。事務(wù)查看數(shù)據(jù)時數(shù)據(jù)所處的狀態(tài),要么是另一并發(fā)事務(wù)修改它之前的狀態(tài),要么是另一事務(wù)修改它之后的狀態(tài),事務(wù)不會查看中間狀態(tài)的數(shù)據(jù)。這稱為可串行性,因為它能夠重新裝載起始數(shù)據(jù),并且重播一系列事務(wù),以使數(shù)據(jù)結(jié)束時的狀態(tài)與原始事務(wù)執(zhí)行的狀態(tài)相同。當(dāng)事務(wù)可序列化時將獲得最高的隔離級別。在此級別上,從一組可并行執(zhí)行的事務(wù)獲得的結(jié)果與通過連續(xù)運行每個事務(wù)所獲得的結(jié)果相同。由于高度隔離會限制可并行執(zhí)行的事務(wù)數(shù),所以一些應(yīng)用程序降低隔離級別以換取更大的吞吐量。

      · 持久性

     事務(wù)完成之后,它對于系統(tǒng)的影響是永久性的。該修改即使出現(xiàn)致命的系統(tǒng)故障也將一直保持。
    DBMS的責(zé)任和我們的任務(wù)

    企業(yè)級的數(shù)據(jù)庫管理系統(tǒng)(DBMS)都有責(zé)任提供一種保證事務(wù)的物理完整性的機制。就常用的SQL Server2000系統(tǒng)而言,它具備鎖定設(shè)備隔離事務(wù)、記錄設(shè)備保證事務(wù)持久性等機制。因此,我們不必關(guān)心數(shù)據(jù)庫事務(wù)的物理完整性,而應(yīng)該關(guān)注在什么情況下使用數(shù)據(jù)庫事務(wù)、事務(wù)對性能的影響,如何使用事務(wù)等等。

    本文將涉及到在.net框架下使用C#語言操縱數(shù)據(jù)庫事務(wù)的各個方面。

    +++@@@+++

    體驗SQL語言的事務(wù)機制

    作為大型的企業(yè)級數(shù)據(jù)庫,SQL Server2000對事務(wù)提供了很好的支持。我們可以使用SQL語句來定義、提交以及回滾一個事務(wù)。

    如下所示的SQL代碼定義了一個事務(wù),并且命名為"MyTransaction"(限于篇幅,本文并不討論如何編寫SQL語言程序,請讀者自行參考相關(guān)書籍):

    DECLARE @TranName VARCHAR(20)

    Select @TranName = ''''MyTransaction''''
    BEGIN TRANSACTION @TranNameGOUSE pubs
    GO

    Update roysched
    SET royalty = royalty * 1.10
    Where title_id LIKE ''''Pc%''''
    GO

    COMMIT TRANSACTION MyTransaction
    GO

    這里用到了SQL Server2000自帶的示例數(shù)據(jù)庫pubs,提交事務(wù)后,將為所有暢銷計算機書籍支付的版稅增加 10%。

    打開SQL Server2000的查詢分析器,選擇pubs數(shù)據(jù)庫,然后運行這段程序,結(jié)果顯而易見。

    可是如何在C#程序中運行呢?我們記得在普通的SQL查詢中,一般需要把查詢語句賦值給SalCommand.CommandText屬性,這里也就像普通的SQL查詢語句一樣,將這些語句賦給SqlCommand.CommandText屬性即可。要注意的一點是,其中的"GO"語句標(biāo)志著SQL批處理的結(jié)束,編寫SQL腳本是需要的,但是在這里是不必要的。我們可以編寫如下的程序來驗證這個想法:

    //TranSql.csusing System;
    using System.Data;
    using System.Data.SqlClient;
    namespace Aspcn
    {
     public class DbTranSql
     {
      file://將事務(wù)放到SQL Server中執(zhí)行
      public void DoTran()
      {
       file://建立連接并打開
       SqlConnection myConn=GetConn();myConn.Open();
       SqlCommand myComm=new SqlCommand();
       try
       {
        myComm.Connection=myConn;
        myComm.CommandText="DECLARE @TranName VARCHAR(20) ";
        myComm.CommandText+="Select @TranName = ''''MyTransaction'''' ";
        myComm.CommandText+="BEGIN TRANSACTION @TranName ";
        myComm.CommandText+="USE pubs ";
        myComm.CommandText+="Update roysched SET royalty = royalty * 1.10 Where title_id LIKE ''''Pc%'''' ";
        myComm.CommandText+="COMMIT TRANSACTION MyTransaction ";
        myComm.ExecuteNonQuery();
       }
       catch(Exception err)
       {
        throw new ApplicationException("事務(wù)操作出錯,系統(tǒng)信息:"+err.Message);
       }
       finally
       {
        myConn.Close();
       }
      }
      file://獲取數(shù)據(jù)連接
      private SqlConnection GetConn()
      {
       string strSql="Data Source=localhost;Integrated Security=SSPI;user id=sa;password=";
       SqlConnection myConn=new SqlConnection(strSql);
       return myConn;
      }
     }

     public class Test
     {
      public static void Main()
      {
       DbTranSql tranTest=new DbTranSql();
       tranTest.DoTran();
       Console.WriteLine("事務(wù)處理已經(jīng)成功完成。");
       Console.ReadLine();
      }
     }
    }


      注意到其中的SqlCommand對象myComm,它的CommandText屬性僅僅是前面SQL代碼字符串連接起來即可,當(dāng)然,其中的"GO"語句已經(jīng)全部去掉了。這個語句就像普通的查詢一樣,程序?qū)QL文本事實上提交給DBMS去處理了,然后接收返回的結(jié)果(如果有結(jié)果返回的話)。

    很自然,我們最后看到了輸出"事務(wù)處理已經(jīng)成功完成",再用企業(yè)管理器查看pubs數(shù)據(jù)庫的roysched表,所有title_id字段以"PC"開頭的書籍的royalty字段的值都增加了0.1倍。

    這里,我們并沒有使用ADO.net的事務(wù)處理機制,而是簡單地將執(zhí)行事務(wù)的SQL語句當(dāng)作普通的查詢來執(zhí)行,因此,事實上該事務(wù)完全沒有用到.net的相關(guān)特性。
    了解.net中的事務(wù)機制

    如你所知,在.net框架中主要有兩個命名空間(namespace)用于應(yīng)用程序同數(shù)據(jù)庫系統(tǒng)的交互:System.Data.SqlClient和System.Data.OleDb。前者專門用于連接Microsoft公司自己的SQL Server數(shù)據(jù)庫,而后者可以適應(yīng)多種不同的數(shù)據(jù)庫。這兩個命名空間中都包含有專門用于管理數(shù)據(jù)庫事務(wù)的類,分別是System.Data.SqlClient.SqlTranscation類和System.Data.OleDb.OleDbTranscation類。

    就像它們的名字一樣,這兩個類大部分功能是一樣的,二者之間的主要差別在于它們的連接機制,前者提供一組直接調(diào)用 SQL Server 的對象,而后者使用本機 OLE DB 啟用數(shù)據(jù)訪問。 事實上,ADO.net 事務(wù)完全在數(shù)據(jù)庫的內(nèi)部處理,且不受 Microsoft 分布式事務(wù)處理協(xié)調(diào)器 (DTC) 或任何其他事務(wù)性機制的支持。本文將主要介紹System.Data.SqlClient.SqlTranscation類,下面的段落中,除了特別注明,都將使用System.Data.SqlClient.SqlTranscation類。

    +++@@@+++

    事務(wù)的開啟和提交

    現(xiàn)在我們對事務(wù)的概念和原理都了然于心了,并且作為已經(jīng)有一些基礎(chǔ)的C#開發(fā)者,我們已經(jīng)熟知編寫數(shù)據(jù)庫交互程序的一些要點,即使用SqlConnection類的對象的Open()方法建立與數(shù)據(jù)庫服務(wù)器的連接,然后將該連接賦給SqlCommand對象的Connection屬性,將欲執(zhí)行的SQL語句賦給它的CommandText屬性,于是就可以通過SqlCommand對象進行數(shù)據(jù)庫操作了。對于我們將要編寫的事務(wù)處理程序,當(dāng)然還需要定義一個SqlTransaction類型的對象。并且看到SqlCommand對象的Transcation屬性,我們很容易想到新建的SqlTransaction對象應(yīng)該與它關(guān)聯(lián)起來。

    基于以上認(rèn)識,下面我們就開始動手寫我們的第一個事務(wù)處理程序。我們可以很熟練地寫出下面這一段程序:

    //DoTran.csusing System;
    using System.Data;
    using System.Data.SqlClient;
    namespace Aspcn
    {
     public class DbTran
     {
      file://執(zhí)行事務(wù)處理
      public void DoTran()
      {
       file://建立連接并打開
       SqlConnection myConn=GetConn();
       myConn.Open();
       SqlCommand myComm=new SqlCommand();
       SqlTransaction myTran=new SqlTransaction();
       try
       {
        myComm.Connection=myConn;
        myComm.Transaction=myTran;
       
        file://定位到pubs數(shù)據(jù)庫 
        myComm.CommandText="USE pubs";
        myComm.ExecuteNonQuery();

        file://更新數(shù)據(jù)
        file://將所有的計算機類圖書
        myComm.CommandText="Update roysched SET royalty = royalty * 1.10 Where title_id LIKE ''''Pc%''''";
        myComm.ExecuteNonQuery();//提交事務(wù)
        myTran.Commit();
       }
       catch(Exception err)
       {
        throw new ApplicationException("事務(wù)操作出錯,系統(tǒng)信息:"+err.Message);
       }
       finally
       {
        myConn.Close();
       }
      }
      file://獲取數(shù)據(jù)連接
      private SqlConnection GetConn()
      {
       string strSql="Data Source=localhost;Integrated Security=SSPI;user id=sa;password=";
       SqlConnection myConn=new SqlConnection(strSql);
       return myConn;
      }
     }

     public class Test{public static void Main()
     {
      DbTran tranTest=new DbTran();
      tranTest.DoTran();
      Console.WriteLine("事務(wù)處理已經(jīng)成功完成。");
      Console.ReadLine();
     }
    }
    }

    顯然,這個程序非常簡單,我們非常自信地編譯它,但是,出乎意料的結(jié)果使我們的成就感頓時煙消云散:

    error CS1501: 重載"SqlTransaction"方法未獲取"0"參數(shù)

    是什么原因呢?注意到我們初始化的代碼:

    SqlTransaction myTran=new SqlTransaction();

    顯然,問題出在這里,事實上,SqlTransaction類并沒有公共的構(gòu)造函數(shù),我們不能這樣新建一個SqlTrancaction類型的變量。在事務(wù)處理之前確實需要有一個SqlTransaction類型的變量,將該變量關(guān)聯(lián)到SqlCommand類的Transcation屬性也是必要的,但是初始化方法卻比較特別一點。在初始化SqlTransaction類時,你需要使用SqlConnection類的BeginTranscation()方法:

    SqlTransaction myTran; myTran=myConn.BeginTransaction();
      
    該方法返回一個SqlTransaction類型的變量。在調(diào)用BeginTransaction()方法以后,所有基于該數(shù)據(jù)連接對象的SQL語句執(zhí)行動作都將被認(rèn)為是事務(wù)MyTran的一部分。同時,你也可以在該方法的參數(shù)中指定事務(wù)隔離級別和事務(wù)名稱,如:

    SqlTransaction myTran;
    myTran=myConn.BeginTransaction(IsolationLevel.ReadCommitted,"SampleTransaction"); 
      
    關(guān)于隔離級別的概念我們將在隨后的內(nèi)容中探討,在這里我們只需牢記一個事務(wù)是如何被啟動,并且關(guān)聯(lián)到特定的數(shù)據(jù)鏈接的。

    先不要急著去搞懂我們的事務(wù)都干了些什么,看到這一行:

    myTran.Commit();

    是的,這就是事務(wù)的提交方式。該語句執(zhí)行后,事務(wù)的所有數(shù)據(jù)庫操作將生效,并且為數(shù)據(jù)庫事務(wù)的持久性機制所保持--即使系統(tǒng)在這以后發(fā)生致命錯誤,該事務(wù)對數(shù)據(jù)庫的影響也不會消失。

    對上面的程序做了修改之后我們可以得到如下代碼(為了節(jié)約篇幅,重復(fù)之處已省略,請參照前文):

    //DoTran.cs……}

    file://執(zhí)行事務(wù)處理
    public void DoTran()
    {
     file://建立連接并打開
     SqlConnection myConn=GetConn();
     myConn.Open();
     SqlCommand myComm=new SqlCommand();

     file://SqlTransaction myTran=new SqlTransaction();
     file://注意,SqlTransaction類無公開的構(gòu)造函數(shù)

     SqlTransaction myTran;

     file://創(chuàng)建一個事務(wù)
     myTran=myConn.BeginTransaction();
     try
     {
      file://從此開始,基于該連接的數(shù)據(jù)操作都被認(rèn)為是事務(wù)的一部分
      file://下面綁定連接和事務(wù)對象
      myComm.Connection=myConn;
      myComm.Transaction=myTran; file://定位到pubs數(shù)據(jù)庫
      myComm.CommandText="USE pubs";
      myComm.ExecuteNonQuery();//更新數(shù)據(jù)
      file://將所有的計算機類圖書
      myComm.CommandText="Update roysched SET royalty = royalty * 1.10 Where title_id LIKE ''''Pc%''''";
      myComm.ExecuteNonQuery();
     
      file://提交事務(wù)
      myTran.Commit();
     }
     catch(Exception err)
     {
      throw new ApplicationException("事務(wù)操作出錯,系統(tǒng)信息:"+err.Message);
      }
     finally
     {
      myConn.Close();
      }
    }
    ……

    到此為止,我們僅僅掌握了如何開始和提交事務(wù)。下一步我們必須考慮的是在事務(wù)中可以干什么和不可以干什么。
     

    該文章轉(zhuǎn)載自'大智の博客':http://www.csafe.cn/article.asp?id=271



    ---------------------------------------------------------
    專注移動開發(fā)

    Android, Windows Mobile, iPhone, J2ME, BlackBerry, Symbian
    posted on 2007-05-10 22:43 TiGERTiAN 閱讀(4491) 評論(2)  編輯  收藏 所屬分類: Other technique

    評論:
    # re: 什么是數(shù)據(jù)庫事務(wù) 2008-05-21 11:42 | 鳳兒
    非常好,支持!  回復(fù)  更多評論
      
    # re: 什么是數(shù)據(jù)庫事務(wù) 2008-05-21 11:46 | TiGERTiAN
    @鳳兒
    呵呵,轉(zhuǎn)的。。  回復(fù)  更多評論
      
    主站蜘蛛池模板: 国产免费一区二区三区在线观看| 免费A级毛片av无码| 亚洲国产成人片在线观看无码| 久草免费手机视频| 亚洲一区二区三区无码国产| 国产伦精品一区二区三区免费迷| 人妻免费久久久久久久了| 亚洲精品美女久久久久| 国产成人免费a在线视频色戒| 少妇性饥渴无码A区免费 | kk4kk免费视频毛片| 亚洲综合激情另类小说区| 国产成人精品免费视频大全五级| a级成人毛片免费图片| 亚洲人成人无码.www石榴| 亚洲色欲色欲www在线丝| 成年午夜视频免费观看视频| 中文字幕无线码免费人妻| 亚洲日本乱码卡2卡3卡新区| 国产亚洲大尺度无码无码专线 | 亚洲国产精品成人精品无码区在线| 亚洲精品免费网站| 中文字幕不卡高清免费| 亚洲人成色99999在线观看| 91亚洲国产在人线播放午夜| 亚洲伊人久久综合中文成人网| 丁香花免费完整高清观看| 免费在线观影网站| 成人午夜免费视频| 亚洲日韩在线中文字幕综合| 亚洲国产精品综合久久久| 国产v亚洲v天堂无码网站| 免费**毛片在线播放直播| 曰批全过程免费视频在线观看| 嫩草成人永久免费观看| 一级做a免费视频观看网站| 欧美亚洲精品一区二区| 亚洲av永久无码精品三区在线4| 亚洲AV无码国产精品麻豆天美| 亚洲精品第一国产综合精品99| 热99re久久免费视精品频软件 |