mysql樂觀鎖 悲觀鎖 共享鎖與排它鎖

2021-08-22 04:34:59 字數 2856 閱讀 3359

樂觀鎖(樂觀併發控制)和悲觀鎖(悲觀併發控制)是指資料庫在對待併發上控制的兩種思想,共享鎖和排它鎖是具體的鎖的實現,且都屬於悲觀鎖。樂觀鎖沒有加鎖

獲取資料的時候不用獲取鎖,直到需要更新資料的時候才去檢查獲取的記錄是否已被其他事務更新,如果更新了則返回錯誤拋異常。注意的是,樂觀鎖中沒有鎖機制,通常的實現方式是用版本號或時間戳實現,比如,事務get了一條記錄,同時獲取到了該條記錄的version,如果需要做更新操作,則對version進行+1操作,插入資料庫時就會檢查資料庫當前的version+1是否與插入的version一致,如果一致則插入,否則拋異常,另只有更新操作才對version做+1操作,獲取資料不會做

獲取資料之前先獲取鎖,再進行操作

lock table 表名1 read|write, 表名2 read|write .................. 【鎖表】

unlock tables 【釋放表】

表共享鎖|讀鎖

所有的客戶端只能讀這個表不能寫這個表

a客戶端對test表設定共享鎖,b客戶端可以讀test表但無法寫操作,直到a客戶端解鎖,b客戶端才能完成寫操作

表排他鎖|寫鎖

所有當前鎖定客戶端可以操作這個表,其他客戶端只能阻塞

a客戶端對test表設定排它鎖,除a客戶端外的所有客戶端都無法進行讀寫操作直至a客戶端解鎖

注意:在鎖表的過程中鎖表客戶端只能操作被鎖定的表,如果要操作其他表,必須把所有要操作的表都鎖定起來!即某一客戶端對test表設定鎖,在未解鎖前不能操作其他未設定鎖的表。其他客戶端可以操作未鎖定的表

共享鎖

set autocommit = 0;

select * from test where id = 1 lock in share mode;

update test set username = 'jack' where id = 1;

commit;

排它鎖set autocommit = 0;

select * from test where id = 1 for update;

update test set username = 'lxj' where id = 2;

commit;

行共享鎖

a客戶端對行加共享鎖後,客戶端b仍可查詢該行記錄並對其加共享鎖,若多個客戶端對同一行加共享鎖會出現死鎖現象。

行排它鎖

a客戶端對某行記錄加了排他鎖,其他客戶端仍可以查詢該記錄,但是不能對該記錄加鎖,會等待獲得鎖。當a客戶端對鎖定的記錄進行修改操作後,釋放排它鎖,其他客戶端才能獲的鎖。

innodb行鎖是通過給索引上的索引項加鎖來實現的,這一點mysql與oracle不同,後者是通過在資料塊中對相應資料行加鎖來實現的。innodb這種行鎖實現特點意味著:只有通過索引條件檢索資料,innodb才使用行級鎖,否則,innodb將使用表鎖!

注意共享鎖與排它鎖都是悲觀鎖,加鎖後其他修改資料的請求都會進入等待過程

使用場景舉例:以mysql innodb為例

商品goods表中有乙個欄位status,status為1代表商品未被下單,status為2代表商品已經被下單,那麼我們對某個商品下單時必須確保該商品status為1。假設商品的id為1。

1. 如果不採用鎖,那麼操作方法如下:

//1.查詢出商品資訊

select status from t_goods where id=1;

//2.根據商品資訊生成訂單

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status為2

update t_goods set status=2;

上面這種場景在高併發訪問的情況下很可能會出現問題。

前面已經提到,只有當goods status為1時才能對該商品下單,上面第一步操作中,查詢出來的商品status為1。但是當我們執行第三步update操作的時候,有可能出現其他人先一步對商品下單把goods status修改為2了,但是我們並不知道資料已經被修改了,這樣就可能造成同乙個商品被下單2次,使得資料不一致。所以說這種方式是不安全的。

2. 使用悲觀鎖來實現:

在上面的場景中,商品資訊從查詢出來到修改,中間有乙個處理訂單的過程,使用悲觀鎖的原理就是,當我們在查詢出goods資訊後就把當前的資料鎖定,直到我們修改完畢後再解鎖。那麼在這個過程中,因為goods被鎖定了,就不會出現有第三者來對其進行修改了。

注:要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性,因為mysql預設使用autocommit模式,也就是說,當你執行乙個更新操作後,mysql會立刻將結果進行提交。

我們可以使用命令設定mysql為非autocommit模式:

set autocommit=0;
設定完autocommit後,我們就可以執行我們的正常業務了。具體如下:

//0.開始事務

begin;/begin work;/start transaction; (三者選一就可以)

//1.查詢出商品資訊

select status from t_goods where id=1 for update;

//2.根據商品資訊生成訂單

insert into t_orders (id,goods_id) values (null,1);

//3.修改商品status為2

update t_goods set status=2;

//4.提交事務

commit;/commit work;

mysql悲觀鎖與樂觀鎖

pessimistic locking 樂觀併發控制 樂觀鎖 和悲觀併發控制 悲觀鎖 是併發控制主要採用的技術手段。悲觀鎖還是樂觀鎖,都是人們定義出來的概念,是一種思想。對於資料庫 悲觀鎖 在資料處理過程,將資料處於鎖定狀態,一般使用資料庫的鎖機制實現。從廣義上來講,前面提到的行鎖 表鎖 讀鎖 寫鎖...

MySQL 悲觀鎖 樂觀鎖

悲觀鎖與樂觀鎖是兩種常見的資源併發鎖設計思路,也是併發程式設計中乙個非常基礎的概念。本文將對這兩種常見的鎖機制在資料庫資料上的實現進行比較系統的介紹。悲觀鎖 pessimistic lock 悲觀鎖的特點是先獲取鎖,再進行業務操作,即 悲觀 的認為獲取鎖是非常有可能失敗的,因此要先確保獲取鎖成功再進...

MySQL 悲觀鎖 樂觀鎖

悲觀鎖與樂觀鎖是兩種常見的資源併發鎖設計思路,也是併發程式設計中乙個非常基礎的概念。本文將對這兩種常見的鎖機制在資料庫資料上的實現進行比較系統的介紹。悲觀鎖 pessimistic lock 悲觀鎖的特點是先獲取鎖,再進行業務操作,即 悲觀 的認為獲取鎖是非常有可能失敗的,因此要先確保獲取鎖成功再進...