mysql,oracle,sql server中的默認事務隔離級別查看,更改 And SQLserver鎖和事務隔離級別的比較與使用

未提交讀(隔離事務的最低級別,只能保證不讀取物理上損壞的數據)

已提交讀(數據庫引擎的默認級別)

可重複讀

可序列化(隔離事務的最高級別,事務之間完全隔離)

 

可串行化比較嚴謹,級別高;

MySQL

mysql默認的事務處理級別是'REPEATABLE-READ',也就是可重複讀

1.查看當前會話隔離級別

select @@tx_isolation;

2.查看系統當前隔離級別

select @@global.tx_isolation;

3.設置當前會話隔離級別

set session transaction isolatin level repeatable read;

4.設置系統當前隔離級別

set global transaction isolation level repeatable read;

Oracle

oracle數據庫支持READ COMMITTED 和 SERIALIZABLE這兩種事務隔離級別。

默認系統事務隔離級別是READ COMMITTED,也就是讀已提交

1.查看系統默認事務隔離級別,也是當前會話隔離級別

--首先創建一個事務
declare
     trans_id Varchar2(100);
  begin
     trans_id := dbms_transaction.local_transaction_id( TRUE );
  end; 

--查看事務隔離級別

SELECT s.sid, s.serial#,

  CASE BITAND(t.flag, POWER(2, 28))
    WHEN 0 THEN 'READ COMMITTED'
    ELSE 'SERIALIZABLE'
  END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');

SQL Server

默認系統事務隔離級別是read committed,也就是讀已提交

1.查看系統當前隔離級別

DBCC USEROPTIONS 

isolation level 這一項的 Value 既是當前的隔離級別設置值

2.設置系統當前隔離級別

SET TRANSACTION ISOLATION LEVEL Read UnCommitted;

其中Read UnCommitted爲需要設置的值

 

------------------------------------------------------------------------------------------

SQLserver鎖和事務隔離級別的比較與使用

 

對象

①     :每條SQL語句

②     隔離:事務

併發問題

丟失更新

未確認的讀取(髒讀)

不一致的分析(非重複讀):多次讀取相同的數據(行)不一致(其他用戶更改update)

幻像讀:多次讀取有不存在和新增的數據(其他用戶插入insert或刪除delete)

隔離級別

隔離級別

髒讀

不可重複讀取

幻像

說明

未提交讀(read uncommitted)

如果其他事務更新,不管是否提交,立即執行

提交讀(read committed默認)

讀取提交過的數據。如果其他事務更新沒提交,則等待

可重複讀(repeatable read)

查詢期間,不允許其他事務update

可串行讀(serializable)

查詢期間,不允許其他事務insert或delete

提交讀

假設存在表A,如下所示

A1

A2

A3

11

21

31

12

22

32

打開查詢分析器並打開兩個連接,分別輸入如下兩個事務:

 

--事務Ⅰ

SET TRANSACTION ISOLATION LEVEL READ Committed

begin tran

update A set A2 = 20 where A1 = 11

waitfor delay '00:00:10'

rollback tran

--事務Ⅱ

SET TRANSACTION ISOLATION LEVEL READ Committed

select * from A where A1 = 11

 

如果先運行事務Ⅰ,然後緊接着運行事務Ⅱ,則事務Ⅱ要等待10秒鐘(一個連接在修改數據塊時別的連接也不能查詢這個數據塊,直到解。反之亦然:讀的時候不能寫和修改)。

如果把事務Ⅱ改爲如下

SET TRANSACTION ISOLATION LEVEL READ UNCommitted

select * from A where A1 = 11

那麼事務Ⅱ不需等待,立即執行(可以看出READ UNCommitted事務select不對數據發出共享

:(這裏主要講解 共享 和 排他 兩種經常用到的)

共享主要是爲了共享讀(select),如果存在事務(一個或多個)擁有對錶中數據(關於數據的多少,視的粒度而定)的共享,不允許對定的數據進行更新(update)(從的角度講,即不允許事務獲取排他,要等到所有的共享都釋放掉)。反之,如果事務對數據已經具有排他(只能有一個),其他的事務就不能對定的數據獲取共享和排他(即排他與共享不能兼容,更多信息請查看兼容性),在此特別強調一下 定的數據 ,因爲有的資料上講解到“一個連接寫的時候,另一個連接可以寫”,實際上寫的這種情況是各個連接的讀寫的數據不是相同的行,也就是說各個連接定的數據不同。

根據以上分析,我們總結爲六個字爲“共享讀,排他寫”。

瞭解了的情況之後,又涉及到一個問題。事務究竟要保持多久呢?

一般來說,共享定時間與事務的隔離級別有關,如果隔離級別爲Read Committed的默認級別,只在讀取(select)的期間保持定,即在查詢出數據以後就釋放了;如果隔離級別爲更高的Repeatable read或Serializable,直到事務結束才釋放。另說明,如果select語句中指定了HoldLock提示,則也要等到事務結束才釋放

排他直到事務結束才釋放。

做出了以上分析,現在我們可能會存在這樣的疑問,到底在執行SQL語句的時候發出什麼樣的呢,這就由事務的隔離級別決定了。一般情況,讀語句(select)發出共享,寫語句(update,insert,delete)發出排他。但是,如果這樣不能滿足我們的要求怎麼辦呢,有沒有更多選擇呢,別急,SQLserver爲我們提供了定提示的概念。

       定提示對SQL語句進行特別指定,這個指定將覆蓋事務的隔離級別。下面對各個定提示分別予以介紹(更多資料請查看SQLserver的聯機幫助),筆者做出了以下分類。

類型1

①     READUNCOMMITTED:不發出

②     READCOMMITTED:發出共享,保持到讀取結束

③     REPEATABLEREAD:發出共享,保持到事務結束

④     SERIALIZABLE:發出共享,保持到事務結束

類型2

①     NOLOCK:不發出。等同於READUNCOMMITTED

②     HOLDLOCK:發出共享,保持到事務結束。等同於SERIALIZABLE

③     XLOCK:發出排他,保持到事務結束。

④     UPDLOCK:發出更新,保持到事務事務結束。(更新:不阻塞別的事物,允許別的事物讀數據(即更新可與共享兼容),但他確保自上次讀取數據後數據沒有被更新)

⑤     READPAST:發出共享,但跳過定行,它不會被阻塞。適用條件:提交讀的隔離級別,行級,select語句中。

類型3

①     ROWLOCK:行級

②     PAGLOCK:頁級

③     TABLOCK:表

④     TABLOCKX:表排他

講解完後,下面結合一個具體實例,具體看一下的使用。

       在很多系統中,經常會遇到這種情況,要保持一個編號的唯一,如會計軟件中的憑證的編號。一種編號的處理是這樣的,把表中的最大編號保存到表中,然後在這個編號上累加,形成新的編號。這個過程對併發處理要求非常高,下面我們就來模擬這個過程,看如何保持編號的唯一性。

       新建一張表code來保存憑證的最大編號。字段如下:編號:bh(numeric(18,0)),憑證表名pinzheng(varchar(50))

假設表中有這樣的一條記錄:

 

Bh

Pinzheng

18000

會計憑證

 

新建一個存儲過程來生成新的憑證編號,如下:

CREATE PROCEDURE up_getbh  AS

       Begin Tran

              Declare @numnewbh numeric(18,0)

              select  @numnewbh = bh FROM code  WITH (UPDLOCK,ROWLOCK) where pinzheng = '會計憑證'

              set @numnewbh = @numnewbh + 1

              update code set  bh = @numnewbh where pinzheng = '會計憑證'

              print @numnewbh

       Commit tran

GO

 

然後,打開查詢分析器,並多開幾個連接(筆者開了8個連接,模擬有8個人同時併發,讀者可以開更多的連接進行試驗),把類似以下這樣的語句複製到每個連接窗口中,

declare @i numeric(18,0)

set @i = 1

while @i = 1

Begin

       if getdate() > '2004-07-22 14:23'  --設定一個時間,到此時間同時執行upgetbh存儲過程

              set @i = 0      

end

exec up_getbh

 

然後,接連運行各個連接,到2004-7-22 14:23 這一刻,各個連接同時運行up_getbh。從運行結果可以看出連接順序出現18001開始個數字,並沒有重號或丟號的現象。

 

分析:由於up_getbh中的select語句使用了更新,因更新之間不能兼容,所以各個連接要等到所有其他的連接釋放掉才能執行,而更新的釋放要等到事務結束,這樣就不會發生號出錯的現象了。

 

附:的兼容性表

現有的授權模式

人生無處不PK

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章