MySQL事務與鎖

Yang`發表於2022-02-06

一、事務與事務特性

在關係型資料庫內,事務是由一個SQL或一組SQL語句組成的邏輯處理單元。也就是說事務就相當於一個盛放SQL的容器,事務中的SQL要麼全部執行成功,要麼所有已經修改的操作都回滾到原來的操作,即一條SQL也不能執行成功。

事務的四大特性(ACID):

  1. 原子性:

    事務作為一個整體被執行,包含在其中的對資料庫的操作要麼全部被執行,要麼都不執行,當在執行過程中出現錯誤,就會回滾到事務開始前的狀態。

  2. 一致性:

    事務的執行結果必須是從一個一致性狀態向另一個一致性狀態的變更。比如,A和B兩人共有100元,那麼不管A轉錢給B,或者B轉錢給A,A+B的金額永遠是100。

  3. 隔離性:

    多個事務併發執行時,一個事務的執行不應影響其他事務的執行。

  4. 永續性:

    一個事務一旦提交,他對資料庫的修改應該永久儲存在資料庫中,任何事務或故障都不應導致資料丟失。

二、MySQL事務的3種執行模式

隱式==自動

顯式==手動

  1. 自動提交事務(隱式開啟、隱式提交)

    MySQL預設的事務執行模式,在每條SQL執行完畢之後自動commit提交。

  2. 隱式事務(隱式開啟、顯式提交)

    由於在MySQL中是預設每條SQL都開啟了事務的,並且每條SQL執行完畢之後都會自動提交,這樣的話就只需要將自動提交關閉就可以了。

    # 零時關閉		(關閉當前資料庫連線在從新連線就恢復了)
    set autocommit = 0;
    
    # 永久關閉		(修改配置檔案my.cnf)
    autocommit = 0
    
    
  3. 顯示事務(顯示開啟、顯示提交)

    這就是我們手動開啟事務,將SQL語句放在我們手動開啟的事務中。

    start transaction;
    
    SQL語句;
    
    commit;		# 提交、或rollback回滾
    

    當使用了commit或者rollback後事務就結束了,在此進入需要從新開始。

三、資料庫讀現象

在高併發場景下,併發的多個事務去操作同一份資料,而產生的一些奇怪的現象,是資料不安全的一種體現。

  1. 髒讀

    一個事務在對一條資料進行了修改,在這個事務還沒有提交時,另一個事務也讀取了這條資料,如果沒有控制,那麼第二個事務讀到的就是一條髒資料,如果第二個事務還需要對這條資料進行操作,那麼這兩個事務之間就存在依賴關係,這就叫髒讀。總結一句話就是事務A讀取到了事務B已經修改了但未提交的資料。

  2. 不可重複讀

    同一個事務在讀取某個資料後,隔一段時間再次讀取該條資料,在這中間該資料被另一個事務給修改,導致兩次讀取的資料不一致。

  3. 幻讀

    幻讀就是不可重複讀的一種現象,同一個事務使用相同的查詢條件讀取以前檢索的資料,卻查詢到了其他事務插入的符合條件的資料,這種現象叫做幻讀。也就是說事務A讀取到了事務B提交的新增資料。

四、鎖機制

鎖是一種保障資料安全的機制,也就是協調多個程式或執行緒併發訪問某一資源的機制。

以互斥鎖為例,讓多個併發的任務同一時間只能有一個可以執行,犧牲了效率換來了資料安全。

鎖的優缺點:

  • 優點:保障併發場景下資料的安全。
  • 缺點:降低了效率。

所以在使用鎖的時候應該儘可能的縮小鎖的範圍,也就是鎖住的資料越小越好,併發能力越高。

鎖的分類:

按照粒度分類:行級鎖、表級鎖、頁級鎖。

按照級別分類:共享鎖、排他鎖。

按照使用方式分類:樂觀鎖(我在改資料的時候沒有人在跟我修改同一份資料,也可以說其實它本身並不是一種鎖,因為它是程式角度的一種寫程式的套路,本質來說並沒有加任何鎖)、悲觀鎖(在我的事務裡面,我在改資料的時候我總認為一定有人在跟我搶,悲觀鎖通常使用資料自帶鎖機制實現的)

行級鎖:

行級鎖它分為共享鎖,排他鎖,是MySQL中粒度最細的一種鎖,所以它的併發能力也是最高的。

對於insert、update、delete語句、innodb會自動給涉及的資料加鎖,而且是排他鎖;

對於普通的select語句,innodb不會加任何鎖,需要手動自己加,可以加兩種型別的鎖;

--共享鎖(s):能同時加到鎖和搶到鎖的是多個,保障讀的一致性
select * from 表名 where ... lock in share mode;
--排他鎖(x):同一時間只能有一個能搶到,保障寫資料的安全
select * from 表名 where ... for update;

鎖的使用:例如

1、事務A對id=3的行加了互斥鎖後,其他事務對id=3的行不能加任何鎖(寫不行,但是可以讀)

2、事務A對id=3的行加了共享鎖後,其他事務對id=3的行只能加共享鎖,或者不加鎖(寫不行,但可以讀)

表級鎖:

表級鎖是MySQL中粒度最大的一種鎖,整張表都被加鎖,當然併發能力也是最低的。

lock table 表名 read(write),表名 read(write),.........;

--SQL語句

unlock tables;	-->釋放當前會話持有的任何鎖

頁級鎖:

頁鎖是取於表鎖和行鎖之間的一種鎖,粒度界於表鎖和行鎖之間的,併發能力一般。

相關文章