日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測(cè)下載網(wǎng)站、值得信賴(lài)的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁(yè)西西教程數(shù)據(jù)庫(kù)教程 → SQL Server事務(wù)和并發(fā)

      SQL Server事務(wù)和并發(fā)

      相關(guān)軟件相關(guān)文章發(fā)表評(píng)論 來(lái)源:小小gogo時(shí)間:2013/12/9 8:33:41字體大。A-A+

      作者:小小gogo點(diǎn)擊:63次評(píng)論:1次標(biāo)簽: sql

      • 類(lèi)型:數(shù)據(jù)庫(kù)類(lèi)大。1.7M語(yǔ)言:英文 評(píng)分:6.6
      • 標(biāo)簽:
      立即下載

      A、Transaction(事務(wù))是什么:

      事物是SQL Server中的基本工作單元。通常它由幾個(gè)讀取和更新數(shù)據(jù)庫(kù)的SQL命令組成,但是這些操作都不被看為最終的,直到發(fā)出一個(gè)COMMIT命令為止。 事務(wù)是作為單一工作單元而執(zhí)行的一系列操作。包括增刪查改。

      2、事務(wù)的種類(lèi):

       事務(wù)分為顯示事務(wù)和隱式事務(wù):

      隱式事務(wù):就是平常我們使用每一條sql 語(yǔ)句就是一個(gè)事務(wù),只不過(guò)他們執(zhí)行完成之后事務(wù)就跟著結(jié)束了。

      顯示事務(wù):就是需要我們來(lái)手寫(xiě)了,這個(gè)時(shí)候就可以進(jìn)行控制事務(wù)的開(kāi)始和結(jié)束了。

       1 --顯式事務(wù)(對(duì)事物可以進(jìn)行控制)
       2 
       3 --開(kāi)始事務(wù)
       4 begin transaction;
       5 update [Sales.Shippers]
       6 set companyname='順豐' where shipperid=5;
       7 
       8 select * from [Sales.Shippers];
       9 
      10 --結(jié)束事務(wù):
      11 --第一種:事務(wù)的回滾
      12 rollback;
      13 
      14 --第二種:事務(wù)的提交
      15 commit;

      3、事務(wù)很重要的四個(gè)屬性: 

       1、原子性:事務(wù)必須是原子工作單位。——在事務(wù)中修改數(shù)據(jù),要么全都執(zhí)行,要么全都不執(zhí)行。在事務(wù)執(zhí)行完成之前(調(diào)提交指令寫(xiě)入到sql的事務(wù)日志之前),出現(xiàn)問(wèn)題或重啟,sql server 會(huì)回滾所有的修改事務(wù)。 但是也有例外的錯(cuò)誤不會(huì)回滾事務(wù)————例如:主鍵沖突和鎖超時(shí)等。  錯(cuò)誤日志會(huì) 捕獲這些錯(cuò)誤的指令,并記錄日志里面,然后執(zhí)行一些操作(例如:回滾事務(wù))

      2、一致性:發(fā)生在同一進(jìn)程的事物里面的 修改和 查詢(xún)是不會(huì)產(chǎn)生沖突的。保持訪(fǎng)問(wèn)的數(shù)據(jù)的一致性。

      3、隔離性:控制數(shù)據(jù)訪(fǎng)問(wèn)的機(jī)制; 說(shuō)明: 一個(gè)事務(wù)正在對(duì)一個(gè)表的數(shù)據(jù)正在修改, 還沒(méi)有執(zhí)行完成;;這時(shí)另一個(gè)事務(wù),想要查詢(xún)里面的數(shù)據(jù),是不能查到的,必須等到 修改的事務(wù)執(zhí)行完成。:sql server 采用的 “鎖”的機(jī)制,將正在修改的事務(wù) 處理的表的數(shù)據(jù) 鎖定。這樣是為了保證數(shù)據(jù)同步,數(shù)據(jù)的一致性。

      4、持久性:  當(dāng)一個(gè)事務(wù)的指令 已經(jīng)提交到 事務(wù)日志里面,即使磁盤(pán)上的數(shù)據(jù)還沒(méi)有修改,這個(gè)時(shí)候數(shù)據(jù)庫(kù)的服務(wù)停止,在服務(wù)重啟的時(shí)候還會(huì)將事務(wù)日志里的指令執(zhí)行(進(jìn)行回復(fù)處理)。保證數(shù)據(jù)的持久性。

      B、什么是并發(fā)性?
      并發(fā)性可以定義為多個(gè)進(jìn)程在相同時(shí)間訪(fǎng)問(wèn)或者更改共享數(shù)據(jù)的能力。既然是能力,那么一個(gè)系統(tǒng)的并發(fā)性就會(huì)有強(qiáng)弱之分。既然如此,我們?cè)撛鯓优袛嘁粋(gè)系統(tǒng)并發(fā)行的強(qiáng)弱呢?
      一般情況而言,一個(gè)系統(tǒng)在互不干擾的情況下可以激活的并發(fā)用戶(hù)的進(jìn)程數(shù)越多,該系統(tǒng)的并發(fā)性就越強(qiáng)。
      可能影響并發(fā)性的一些原因分析:
      當(dāng)正在更改數(shù)據(jù)的進(jìn)程阻止其他進(jìn)程讀取該數(shù)據(jù)時(shí),或者當(dāng)讀取數(shù)據(jù)的進(jìn)程阻止其他進(jìn)程更改該數(shù)據(jù)時(shí),并發(fā)行會(huì)減弱。另外,當(dāng)多個(gè)進(jìn)程試圖同時(shí)更改相同數(shù)據(jù)時(shí),且無(wú)法在不犧牲數(shù)據(jù)的一致性的前提下都能成功時(shí),并發(fā)性也會(huì)受到影響。對(duì)于并發(fā)性的理解我們和容易聯(lián)想到鐵道部的訂票網(wǎng)站。由于處理并發(fā)性能力不夠,導(dǎo)致訂票高峰出現(xiàn)奔潰現(xiàn)象,對(duì)網(wǎng)絡(luò)訂票造成不良影響。由此可見(jiàn),一個(gè)大型網(wǎng)站的數(shù)據(jù)庫(kù)系統(tǒng)提高處理并發(fā)性的能力是在必要。

      處理并發(fā)性的方法:

      SQLServer 2008提供兩種方法:樂(lè)觀(guān)和悲觀(guān)兩個(gè)模型。我們可以通過(guò)一下命令來(lái)指定:
      SETTRANSACTION ISOLATION LEVEL(事物的隔離級(jí)別)來(lái)指定。

      兩者的區(qū)別:
      在兩種模型中,兩個(gè)進(jìn)程試圖在相同時(shí)間修改相同數(shù)據(jù)時(shí),可能會(huì)出現(xiàn)沖突。那么這兩個(gè)模型之間的區(qū)別在于沖突是在出現(xiàn)前被避免還是在出現(xiàn)后采取某種方式進(jìn)行處理。
      悲觀(guān)并發(fā)模型:
      對(duì)于悲觀(guān)并發(fā)SQL Server默認(rèn)的行為是獲取鎖來(lái)阻塞對(duì)另一個(gè)進(jìn)程正在使用的數(shù)據(jù)的訪(fǎng)問(wèn)。悲觀(guān)并發(fā)假設(shè)系統(tǒng)中有足夠的數(shù)據(jù)修改操作,因而給定的任何一個(gè)讀寫(xiě)操作都可能受到另外一個(gè)用戶(hù)的數(shù)據(jù)修改操作的影響。悲觀(guān)并發(fā)通過(guò)獲得正在被讀取數(shù)據(jù)上的鎖,使其他進(jìn)程無(wú)法修改該數(shù)據(jù)而避免沖突。換言之,在悲觀(guān)模型下,讀取者阻塞寫(xiě)入者,寫(xiě)入者也阻塞讀取者。

      樂(lè)觀(guān)并發(fā)模型:
      樂(lè)觀(guān)并發(fā)假設(shè)系統(tǒng)中有足夠少的數(shù)據(jù)修改操作,因而任何單個(gè)事物都不太可能另一個(gè)事物正在修改的數(shù)據(jù)。樂(lè)觀(guān)并發(fā)的默認(rèn)行為是使用行版本控制來(lái)允許數(shù)據(jù)讀取者看到修改之前的數(shù)據(jù)狀態(tài)。數(shù)據(jù)行教老的版本被保存,所以讀取數(shù)據(jù)的進(jìn)程可以看到進(jìn)程開(kāi)始讀取時(shí)的數(shù)據(jù),不會(huì)受到對(duì)該數(shù)據(jù)正在做出任何更改的進(jìn)程的影響。換言之,讀取者不阻塞寫(xiě)入者,寫(xiě)入者也不阻塞讀取者,但是,寫(xiě)入者可以而且會(huì)阻塞寫(xiě)入者,這也是導(dǎo)致沖突的原因所在。這時(shí)SQL Server在沖突出現(xiàn)時(shí)產(chǎn)生一個(gè)錯(cuò)誤信息,但是是由應(yīng)用程序來(lái)負(fù)責(zé)影響該錯(cuò)誤。

      上面將基本的事務(wù)介紹了一下,下面開(kāi)始介紹并發(fā)。所以必須要介紹就是事務(wù)的“鎖”。

      4、事務(wù)中的鎖

       事務(wù)中都含有什么鎖呢?

      最常用的鎖:排它鎖(獨(dú)占鎖)和共享鎖,還有其他的鎖,這里就不做介紹了,比如:更新鎖、架構(gòu)鎖、意向鎖等。

      5、排它鎖和共享鎖

       排它鎖:

      當(dāng)一個(gè)事務(wù)執(zhí)行更新修改操作的時(shí)候會(huì)申請(qǐng)排它鎖,主要是在寫(xiě)操作里面使用。需要注意的兩點(diǎn):1、一個(gè)事務(wù)含有排它鎖,就不能含有其他任何鎖。2、一條數(shù)據(jù)只能被一個(gè)排它鎖鎖住,就不能再被其他排他鎖鎖定。

      共享鎖:

       主要是在讀操作中使用,并且多個(gè)事務(wù)可以同時(shí)對(duì)一條數(shù)據(jù)使用共享鎖。

      排它鎖和共享鎖最重要的區(qū)別:排它鎖是不能被控制他的處理方式和時(shí)間,但是共享鎖是可以控制其隔離級(jí)別來(lái)控制其處理的時(shí)間。

      1 begin transaction;
      2 update [Sales.Shippers] set companyname='順豐' where shipperid=5;
      3 --事務(wù)還沒(méi)有查詢(xún)完成,為這條數(shù)據(jù) 加上一個(gè) 排它鎖。這時(shí)這條數(shù)據(jù)就不能被其他進(jìn)程 訪(fǎng)問(wèn)到

      事務(wù)還沒(méi)有執(zhí)行完成,再開(kāi)一個(gè)線(xiàn)程,執(zhí)行查詢(xún)操作

      1 select * from [Sales.Shippers] where shipperid=5

      因?yàn)樽x操作默認(rèn)使用的共享鎖,但是這個(gè)時(shí)候這條數(shù)據(jù)已經(jīng)被其他線(xiàn)程的排它鎖鎖住,所以會(huì)造成阻塞,直到排它鎖釋放。

      6、隔離級(jí)別 

       首先要先明白三點(diǎn):

      1、用于控制并發(fā)用戶(hù)如何讀寫(xiě)數(shù)據(jù)的操做。

      2、讀操作默認(rèn)使用共享鎖;寫(xiě)操作需要使用排它鎖。

      3、讀操作能夠控制他的處理的方式,寫(xiě)操作不能控制它的處理方式

      隔離級(jí)別分為六種:

      read uncommited(讀取未提交數(shù)據(jù)),read commited(讀取已提交數(shù)據(jù))讀取的默認(rèn)方式,repeatable read(可重復(fù)讀),serializable(可序列化),snapshot(快照),read commited snapshot(已經(jīng)提交讀隔離)(后兩個(gè)是sql server 2005 里面 引入的)。隔離的強(qiáng)度依次遞增。

       1、read uncommitted:

      1 select * from [Sales.Shippers] where shipperid=3;

       查詢(xún)結(jié)果:

      在本線(xiàn)程內(nèi)執(zhí)行:

      1 begin transaction;
      2 update [Sales.Shippers] set companyname='圓通' where shipperid=3;

      在另外一個(gè)線(xiàn)程內(nèi) 使用 read uncommitted 隔離級(jí)別 查詢(xún)數(shù)據(jù):

      1 --設(shè)置讀操作的隔離級(jí)別
      2 set transaction isolation level read uncommitted;
      3 select * from [Sales.Shippers] where shipperid=3;

       查詢(xún)結(jié)果:

      如果這個(gè)時(shí)候?qū)⒛莻(gè)事務(wù)回滾,那么這個(gè)時(shí)候  查詢(xún)到的數(shù)據(jù)就是“臟數(shù)據(jù)”。

      總結(jié):

      read uncommitted:最低的隔離級(jí)別:查詢(xún)的時(shí)候不會(huì)請(qǐng)求共享鎖,所以不會(huì)和排它鎖產(chǎn)生沖突(不會(huì)等待排它鎖執(zhí)行完),查詢(xún)效率非常高,速度飛快。但是缺點(diǎn):會(huì)查到“臟數(shù)據(jù)”(排它鎖的事務(wù)已經(jīng)將數(shù)據(jù)修改,還沒(méi)提交,這個(gè)時(shí)候查詢(xún)到的數(shù)據(jù) 是已經(jīng)更改過(guò)的。如果事務(wù)回滾,就是“臟數(shù)據(jù)”)

      優(yōu)點(diǎn):查詢(xún)效率非常高,速度非常快。

      缺點(diǎn):會(huì)產(chǎn)生“臟數(shù)據(jù)”

      適用性:

      適用于 像聊天軟件的 聊天記錄,會(huì)是軟件的運(yùn)行速度非?。 但是不適用于 商務(wù)軟件。尤其是銀行

      2、read committed

       讀取的默認(rèn)隔離級(jí)別就是read committed 和上面正好相反。如果上面情況,采用read committed 隔離級(jí)別查詢(xún)的話(huà)查到的就是還沒(méi)有更改之前的數(shù)據(jù)。

       所以在這里就不再演示。

      3、repeatable read:

       查詢(xún)的時(shí)候會(huì)加上共享鎖,但是查詢(xún)完成之后,共享鎖就會(huì)被撤銷(xiāo)。比如一些購(gòu)票系統(tǒng),如果查到票了,當(dāng)買(mǎi)的時(shí)候就沒(méi)有,這是不行的。所以要在查詢(xún)到數(shù)據(jù)之后做一些延遲共享鎖,進(jìn)而阻塞排它鎖來(lái)修改。

      在查詢(xún)線(xiàn)程里面執(zhí)行sql語(yǔ)句:

      1 set transaction isolation level repeatable read;
      2 begin transaction;
      3 select * from [Sales.Shippers] where shipperid=4;

      然后在 另外一個(gè)線(xiàn)程內(nèi)執(zhí)行修改語(yǔ)句:

      update [Sales.Shippers] set companyname='shit' where shipperid=4;

      這個(gè)時(shí)候會(huì)將更改的線(xiàn)程阻塞掉:

      4、serializable(可序列化)

       更高級(jí)的 隔離。用戶(hù)解決“幻讀”。就是使用上面的  加上共享鎖 并不撤銷(xiāo),如果鎖定的 一行數(shù)據(jù),那么 其他的進(jìn)程 還可以對(duì) 其他的數(shù)據(jù)進(jìn)行操作,也可以 進(jìn)行新增和刪除的操作。   所以如果想要在查詢(xún)的時(shí)候,不能對(duì)整張表進(jìn)行任何操作,那么就要 將表的結(jié)構(gòu)也 鎖定    (就需要使用 更強(qiáng)的 鎖定)

      在查詢(xún)線(xiàn)程執(zhí)行sql語(yǔ)句:

      1 set transaction isolation level serializable;
      2 
      3 begin transaction;
      4 select * from [Sales.Shippers] where shipperid=3;

      那么在另外一個(gè)線(xiàn)程執(zhí)行下面兩個(gè)語(yǔ)句,不論那一條語(yǔ)句都會(huì)阻塞住:

      update [Sales.Shippers] set companyname='聯(lián)邦' where shipperid=3;
      
      insert into [Sales.Shippers] (companyname,phone) values('韻達(dá)','12345678')

      總結(jié):

      可序列話(huà) 隔離讀操作:用戶(hù) 解決 幻影數(shù)據(jù)(將標(biāo)的數(shù)據(jù)和表的結(jié)構(gòu)都鎖定),是并發(fā)降低...隔離級(jí)別越高,并發(fā)越低,但是效率越低,所以不是要確定使用  最好不要使用

      下面兩種隔離級(jí)別是在 sql server 2005才出現(xiàn)的,隔離級(jí)別更高:

      5、snapshot(快照)

       為數(shù)據(jù)產(chǎn)生一個(gè)臨時(shí)數(shù)據(jù)庫(kù),當(dāng)sql server 數(shù)據(jù)更新之前將當(dāng)前數(shù)據(jù)庫(kù)復(fù)制到 tempdb數(shù)據(jù)庫(kù)里面,查詢(xún)就是從tempdb數(shù)據(jù)庫(kù)中查詢(xún)

      --設(shè)置數(shù)據(jù)庫(kù)支持快照隔離級(jí)別:
      alter database ssdemo set allow_snapshot_isolation on;--這個(gè)時(shí)候會(huì)產(chǎn)生一個(gè)臨時(shí)數(shù)據(jù)庫(kù)(寫(xiě)操作的排它鎖鎖定的是 現(xiàn)實(shí)存在的數(shù)據(jù)庫(kù),,讀操作的讀取的是 臨時(shí)數(shù)據(jù)庫(kù))

       在一個(gè)線(xiàn)程中執(zhí)行 更新操作,用排它鎖鎖定當(dāng)前數(shù)據(jù)

      begin transaction;
      --使用 排它鎖(獨(dú)占鎖)X,鎖定 下面的那條數(shù)據(jù)
      update [Sales.Shippers] set companyname='飛鳳' where shipperid=3;

      這個(gè)時(shí)候在在另外一個(gè)線(xiàn)程中查詢(xún)這條數(shù)據(jù)(默認(rèn)的隔離級(jí)別),就會(huì)將當(dāng)前線(xiàn)程阻塞。

      如果使用 snapshot 隔離級(jí)別查詢(xún)就不會(huì)阻塞。

      1 set transaction isolation level snapshot;
      2 --下面的就可以  從臨時(shí)數(shù)據(jù)庫(kù)中查詢(xún)到數(shù)據(jù)
      3 begin transaction;
      4 --使用 共享鎖 S
      5 select * from [Sales.Shippers] where shipperid=3;--查詢(xún)到的 是還沒(méi)有完成更新之前的數(shù)據(jù)

      但是同時(shí)也會(huì)帶來(lái)兩個(gè)問(wèn)題:

      1、當(dāng) 另外一個(gè)事務(wù)  已經(jīng)提交,但是這邊的查詢(xún)到數(shù)據(jù)還是沒(méi)有修改。因?yàn)?每次查詢(xún)到的快照是針對(duì)于 本次回話(huà)對(duì)應(yīng)的那個(gè) transaction 的,因?yàn)樵谶@個(gè)事務(wù)里面是沒(méi)有修改的,所以查詢(xún)到的數(shù)據(jù)是沒(méi)有修改的。

      2、(更新問(wèn)題)因?yàn)?那邊的數(shù)據(jù)已經(jīng)是 飛鳳公司了,但是這里還是   聯(lián)邦,所以,在這個(gè)事務(wù)里面是不能對(duì)表進(jìn)行修改,因?yàn)樵L(fǎng)問(wèn)的是臨時(shí)數(shù)據(jù)庫(kù),想要對(duì) 數(shù)據(jù)庫(kù)修改是不可能的(sql server 就會(huì)報(bào)錯(cuò),阻止修改) 

      針對(duì)于上面兩個(gè)問(wèn)題,所以下面 更高的隔離級(jí)別出現(xiàn)了 read committed snapshot:

      6、read committed snapshot

       首先開(kāi)啟數(shù)據(jù)庫(kù)的 read committed snapshot 隔離級(jí)別:

      1 --設(shè)置 數(shù)據(jù)庫(kù) 為 讀取已經(jīng)提交的快照 開(kāi)啟
      2 alter database ssdemo set read_committed_snapshot on;

      在一個(gè)線(xiàn)程中執(zhí)行:

      begin transaction;
      update [Sales.Shippers] set companyname='聯(lián)邦' where shipperid=3;

      在另外一個(gè)線(xiàn)程中:

      1 --不用顯示聲明使用  read committed snapshot 隔離級(jí)別,因?yàn)樵O(shè)置完 read_committed_snapshot 隔離級(jí)別啟動(dòng),默認(rèn)就是 read commited snapshot 隔離級(jí)別
      2 begin transaction;
      3 select * from [Sales.Shippers] where shipperid=3;--查詢(xún)到是 已經(jīng)提交之后的數(shù)據(jù)
      4 
      5 update [Sales.Shippers] set companyname='xiaoxiao' where shipperid=3;

      這個(gè)時(shí)候查詢(xún)到的數(shù)據(jù)是還沒(méi)有更改之前的,如果將 前面的那個(gè)回話(huà)提交,那么在查詢(xún) 查詢(xún)到的數(shù)據(jù)是 提交修改之后的數(shù)據(jù)。所以解決了上面的問(wèn)題1.

      如果在修改的話(huà)。也是在第一個(gè) 更新線(xiàn)程中的事務(wù)更新之后的數(shù)據(jù)進(jìn)行執(zhí)行修改的操作,不會(huì)報(bào)錯(cuò)。

        相關(guān)評(píng)論

        閱讀本文后您有什么感想? 已有人給出評(píng)價(jià)!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過(guò)難過(guò)
        • 5 囧
        • 3 圍觀(guān)圍觀(guān)
        • 2 無(wú)聊無(wú)聊

        熱門(mén)評(píng)論

        最新評(píng)論

        發(fā)表評(píng)論 查看所有評(píng)論(1)

        昵稱(chēng):
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字?jǐn)?shù): 0/500 (您的評(píng)論需要經(jīng)過(guò)審核才能顯示)