MySQL事務和鎖機制

MySQL技術——事務和鎖機制

    • 一、事務
      • (1)概述
      • (2)ACID特性
      • (3)事務并發存在的問題
      • (4)事務的隔離級別
    • 二、鎖機制
      • (1)鎖的力度
      • (2)表的分類: 排他鎖、共享鎖
      • (3)串行化解決幻讀(虛讀)問題 :間隙鎖
      • (4)意向共享鎖和意向排他鎖
      • (5)死鎖
      • (6)鎖的優化建議
    • 三、多版本并發控制(MVCC)
    • 四、MySQL優化問題
    • 五、總結

一、事務

(1)概述

事務是數據庫區別于文件系統的重要特征之一。在文件系統中,如果正在寫文件,但是操作系統奔潰了,這個文件就很有可能被破壞。當然,有一些機制可以把文件回復到某個時間點。不過,如果需要保證兩個文件同步,這些文件系統可能就顯得無能為力了,例如,當需要更新兩個文件時,更新完一個文件后,在更新完第二個文件之前系統重啟了,就會產生兩個不同步的文件,因此這也就是數據庫系統引入事務的主要目的

一個事務是由一條或者多條數據庫操作SQL語句所組成的一個不可分割的單元,只有當事務中的所有操作都正常執行完畢后,整個事務才會被提交給數據庫;如果由部分事務處理失敗,那么事務就要回退到最初的狀態。因此事務要么全部執行成功,要么全部失敗

(2)ACID特性

每一個事務都必須滿足下面的4個特性:

  • 事務的原子性(Atomic): 事務是一個不可分割的整體,事務必須具有原子特性,要么全執行,要么全不執行
  • 事務的一致性(Consistency): 一個事務執行之前和執行之后,數據庫數據必須保持一致性狀態。數據庫的一致性狀態必須由用戶來負責,由并發控制機制實現
  • 事務的隔離性(Isolation): 當兩個或者多個事務并發執行時,為了保證數據的安全性,將一個事務內部的操作與其他事務的存在隔離起來,不被其他正在執行的事務看到,使得并發執行的各個事務之間不能相互影響 | 鎖 + MVCC
  • 事務的持久性(Durability): 事務完成(commit)后,DBMS保證它對數據庫中的數據是永久性的,即使數據庫因為故障出錯,也應該能夠快速恢復數據

(3)事務并發存在的問題

如果事務處理不經過隔離,并發執行事務是通常會發生以下問題:

  • 臟讀(Dirty Read): 一個事務讀取了另一個事務為提交的數據,例如當事務A和事務B并發執行時,當事務A更新后,事務B查詢讀取到事務A尚未提交的數據,此時事務A回滾,則事務B讀到的數據就是無效的臟讀數據(事務B讀取到來事務A未提交的數據
  • 不可重復讀(NonRepeatable Read): 一個事務的操作導致另一個事務前后兩處讀取到不同的數據。即當事務A和事務B并發執行時,當事務B查詢讀取到數據后,事務A更新操作更改事務B查詢到的數據,此時事務B再次去讀取該數據,發現前后兩處讀的數據不一樣(事務B讀取了事務A已經提交的數據
  • 虛讀 / 幻讀(Phantom Read): 一個事務的操作導致另一個事務前后兩次查詢的結果 數據量不同 ,即當事務A和事務B并發執行時,當事務B查詢讀取數據后,事務A新增或者刪除了一條滿足事務B查詢條件的記錄,此時事務B再去查詢,發現查詢到前一次不存在的記錄,或者前一次查詢的一些記錄不見了(事務B讀取了事務A新增的數據,或者讀不到事務A刪除的數據

(4)事務的隔離級別

MySQL默認支持四種隔離級別,如下圖:

隔離級別臟讀不可重復讀虛讀 / 幻讀
未提交讀:TRANSACTION_READ_UNCOMMITTED可以可以可以
已提交讀:TRANSACTION_READ_COMMITTED不可以可以可以
可重復讀:TRANSACTION_REPEATABLE_READ不可以不可以update 可以
串行化: TRANSACTION_SERIALIZABLE不可以不可以不可以
  • 串行化是最高的事務級別,由于事務隔離級別越高,為避免沖特所花費的性能也越多
  • 在“可重復讀”級別中,實際上是可以解決部分的虛讀問題,但是不能防止update更新產生的虛讀問題,還是要串行化隔離級別

select @@transation_isolation; mysql默認的隔離級別:可重復讀在這里插入圖片描述

我們現在一一列舉各種隔離級別會出現的結果

  • 未提交讀 READ_UNCOMMITTED
    在這里插入圖片描述

  • 已提交讀 READ_COMMITTED
    在這里插入圖片描述

  • 可重復讀 REPEATABLE-READ,這里對于幻讀就不演示了,可以自行驗證
    在這里插入圖片描述

  • 串行化 SERIALIZABLE
    在這里插入圖片描述

二、鎖機制

(1)鎖的力度

鎖的力度分為兩種:

  • 表級鎖:對整張表加鎖,開銷小,加鎖塊,不會出現死鎖;鎖的力度大,發送鎖沖突的概率高,并發度低
  • 行級鎖:對某行記錄加鎖。開銷大,加鎖慢,會出現死鎖;鎖定力度最小,發生鎖沖突的概率最低,并發度高
    • InnoDB行鎖是通過給索引上的索引項加鎖來實現的,而不是給表的行記錄加鎖實現的,這就意味著只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則InnoDB將使用表鎖。
    • 由于InnoDB的行鎖實現是針對索引字段添加的鎖,不是針對行記錄加的鎖,因此雖然訪問的是InnoDB引擎下表的不同行,但是如果使用相同的索引字段作為過濾條件,依然會發生鎖沖突,只能串行進行,不能并發進行。
    • 即使SQL中使用了索引,但是經過MySQL的優化器后,如果認為全表掃描比使用索引效率更高,此時會放棄使用索引,因此也不會使用行鎖,而是使用表鎖,比如對一些很小的表,MySQL就不會去使用索引。

(2)表的分類: 排他鎖、共享鎖

  • 共享鎖(Shared)
  • 排他鎖(Exclusive):又稱X鎖,寫鎖
  • 共享鎖(Shared):又稱S鎖,讀鎖

X和S鎖之間由以下關系:SS可以兼容,SX、XX、XS之間是互斥的

  • 一個事務對數據對象O加了S鎖,可以對O進行讀取操作但不能進行更新操作。加鎖期間其他事務能對O加S鎖但不能加X鎖
  • 一個事務對數據對象O加了X鎖,就可以對O進行讀取和更新。加鎖期間其他事務不能對O加任何鎖
顯示加鎖語句
select ... lock in share mode;  #強制獲取共享鎖
select ... for update;	   #獲取排他鎖

下面我們來演示一下,兩種鎖的效果

假設我們開啟了兩個事務,默認工作在隔離級別為可重復讀,兩個事務先后執行以下語句 select * from stu where id = 2 for update,根據上述推導,XX是不可兼容的,所以前一個執行sql語句的事務會對當前查詢的記錄加一把排他鎖,后執行sql語句的事務肯定會被阻塞;若后執行sql語句的事務換成執行... lock in share mode,同樣也是阻塞,因為XS也是不兼容的;若后執行的事務獲取其他記錄的鎖,如id = 3 for update,該記錄沒有加X鎖,因此可以執行
在這里插入圖片描述
我們再來看看另外一條sql語句 select .. name = 'aaa' for update
在這里插入圖片描述
select 'bbb'竟然也會阻塞!!!
這里注意:InnoDB的行鎖是加在索引項上面的,并不是單純的給行記錄加鎖;如果過濾條件沒有索引的話,name只是普通字段,使用的就是表鎖,而不是行鎖!!!
這里如果我們給name字段添加索引的話,就是加行鎖,使得’bbb’能夠執行
在這里插入圖片描述
我們來看看隔離級別為 SERIALIZABLE的結果
在這里插入圖片描述

(3)串行化解決幻讀(虛讀)問題 :間隙鎖

當我們用范圍條件而不是等值條件去查詢數據時,并請求共享或者排他鎖時,InnoDB會給符合條件的已有數據記錄的索引項加鎖;對于鍵值在條件范圍內但是并不存在的記錄,叫做“間隙(GAP)”,InnoDB也會對這個“間隙”加鎖,這種鎖機制就是所謂的間隙鎖。

目的:防止幻讀,以滿足川=串行化隔離級別的要求

鎖的三張算法:

  • record lock:行鎖
  • gap lock:間隙鎖
  • next-key lock:record lock + gap lock

示例1 范圍查詢:按過濾條件分為:使用主鍵索引 或者 輔助索引
在這里插入圖片描述
在這里插入圖片描述


示例二 等值查詢
在這里插入圖片描述
在這里插入圖片描述

(4)意向共享鎖和意向排他鎖

在使用表鎖的時候,涉及到的效率問題
要獲取一張表的S或者X鎖,需要檢查這張表沒有被其他事務獲取過X鎖,這表里的數據沒有被其他事務獲取過行鎖X鎖,那么如果這張表有非常多的數據,是一行一行的檢查???
意向共享鎖和意向排他鎖就是用來解決這個問題

  • 意向共享鎖(IS鎖): 事務計劃給記錄加行共享鎖,事務在給一行記錄加共享鎖前,必須先取得該表的IS鎖
  • 意向排他鎖(IX鎖): 事務計劃給記錄加行排他鎖,事務在給一行記錄加排他鎖前,必須先取得該表的IX鎖

當我們需要獲取表的X鎖時,不需要再檢查表中的哪些行被(X或者S)鎖占用,只需要檢查IX和IS鎖即可!

如下圖的 X和S都是表鎖

XIXSIS
XConflictConflictConflictConflict
IXConflict兼容Conflict兼容
SConflictConflict兼容兼容
ISConflict兼容兼容兼容

1、意向鎖是由InnoDB存儲引擎獲取行鎖之前自己獲取的
2、意向鎖之間都是兼容的,不會產生沖突
3、意向鎖存在的意義是為了更高效的獲取表鎖
4、意向鎖是表級鎖,協調表鎖和行鎖的共存關系,主要目的是顯示事務正在鎖定某行或者試圖鎖定某行。

(5)死鎖

MyISAM表鎖是deadlock free的,這是因為MyISAM總是一次獲得所需的所有鎖,要么全部滿足,要么等待,因此不會發生死鎖。但在InnoDB中,出來的單個SQL組成的事務外,鎖是逐步獲得的,即鎖的力度比較小,發生死鎖也是可能的,如下:

在這里插入圖片描述
在這里插入圖片描述

死鎖問題一般都是我們自己的應用造成的,和多線程編程的死鎖情況相似,大部分都是由于我們多個線程在獲取多個鎖資源的時候,獲取的順序不同而導致的死鎖問題。因此我們應用在對數據庫的多個表做更新的時候,不同的代碼段,應對這些表按相同的順序進行更新操作,以防止鎖沖突導致死鎖問題。

(6)鎖的優化建議

  1. 盡量使用較低的隔離級別
  2. 設計合理的所有并盡量使用索引訪問數據,使鎖更加準確,減少鎖沖突的機會提高并發能力
  3. 選擇合理的事務大小,小事務發生鎖沖突概率小
  4. 不同的程序訪問一組表時,應盡量約定以相同的順序訪問各表,對于一個表而言,盡可能以固定的順序存取表中的行,這樣也能減少死鎖的發生
  5. 盡量用相等條件訪問數據,這樣可以避免間隙鎖對并發插入的影響
  6. 不要申請超過實際需要的鎖級別
  7. 除非必須,查詢時不要顯示加鎖

三、多版本并發控制(MVCC)

MVCC(Multi-Version Concurrency Control,簡稱MVCC),是MySQL中基于樂觀鎖理論實現隔離級別的方式,用于已提交讀可重復讀隔離級別的實現,也經常被稱為多版本并發控制。MVCC機制會生成一個數據請求時間點的一致性數據快照(Snapshot),并用這個快照來提供一定級別的一致性讀取。從用戶的角度來看,就是數據庫提供同一組數據的多個版本(系統版本號和事務版本號)。

MVCC多版本控制的讀操作分為兩類:

  • 快照讀:讀的是記錄的可見版本,不用加鎖,如select
  • 當前讀:讀的是記錄的最新版本,并且返回當前的記錄,如insert,delete,select,update,select … lock in share mode / for update

MVCC: 每一行記錄實際上有多個版本,每個版本的記錄除了數據本身之外,增加了其它字段

  • DB_TRX_ID:記錄當前事務ID
  • DB_ROLL_PTR:指向undo log日志上數據的指針

已提交讀: 每次執行語句的時候都重新生成一次快照(Read View),每次select查詢時。
可重復讀: 同一個事務開始的時候生成一個當前事務全局性的快照(Read View),第一次select查詢時。

快照讀取原則:

  1. 版本未提交無法生成快照
  2. 版本已提交,但是在快照創建后提交,無法讀取
  3. 版本已提交,但是在快照創建前提交,可以讀取
  4. 當前事務內自己更新,可以讀到

在這里插入圖片描述

InnoDB提供了兩個讀取操作:

  • 鎖定讀: S、X鎖
  • 非鎖定讀: 其依賴于 undo log 回滾日志

undo log:回滾日志,保存了事務發生之前的數據的一個版本,用于執行時的回滾操作,同時也是實現多版本并發控制(MVCC)下的關鍵技術
在這里插入圖片描述

redo log:重做日志,用于記錄事務操作的變化,確保事務的持久性。redo log是在事務開始后就開始記錄,不管事務是否提交都會記錄下來,在異常發生時(如數據持久化過程中掉電),InnoDB會使用redo log恢復到掉電前的時刻,保證數據的完整性。InnoDB修改操作數據時,不是直接修改磁盤上的數據,實際只是修改Buffer Pool中的數據。InnoDB總是先把Buffer Pool中的數據改變記錄到redo log中,用來進行崩潰后的數據恢復。 優先記錄redo log,然后再由專門的線程將Buffer Pool中的臟數據刷新到磁盤上。
在這里插入圖片描述

四、MySQL優化問題

對于MySQL優化問題分為3種:

  • SQL和索引的優化: 慢查詢日志 -》 根據表的數據量等設置合理的慢查詢時間 -》 記錄慢查詢sql -》 explain 分析sql執行計劃 -》 優化措施
  • 應用上的優化:
    • 連接數據庫:訪問頻繁,引入連接池中間件
    • 引入緩存(存儲熱點數據) redis(重點!!!)
      • 緩存數據一致性問題?
      • 緩存穿透
      • 緩存雪崩
      • redis還有哪些功能?
  • mysql server上的優化: 各種參數配置!
    • MySQL的查詢緩存 query_cache_typequery_cache_size
    • 索引和數據緩存, innodb_buffer_pool_size越高,磁盤IO越少
    • MySQL線程緩存thread_cache_size
    • 并發連接數量和超時時間 max_connectionswait_timeout

五、總結

  • 事務的特征 ACID—— 原子性、一致性、隔離性、持久性
  • 事務并發的問題——臟讀、不可重復度、虛讀/幻讀
  • 事務的隔離級別——未提交讀、已提交讀、可重復讀、串行話
  • 鎖的力度——行級鎖、表級鎖
  • 鎖的分類——排他鎖、共享鎖(意向共享鎖、意向排他鎖)
  • 使用非索引字段獲取排他鎖時,實際上是直接加了表鎖
  • 串行化解決的幻讀問題——間隙鎖(范圍查詢、等值查詢)
  • 鎖的優化建議——低隔離級別、設計合理索引、使用相同順序、盡可能等值查詢
  • 可重復讀和已提交讀隔離級別 通過MVCC機制中的快照讀(非鎖定讀)保證,依賴于undo log回滾日志
  • MYSQL優化——sql和索引、應用層、mysql server

🌻🌻🌻以上就是有關于MySQL事務和鎖機制的內容,如果聰明的你瀏覽到這篇文章并覺得文章內容對你有幫助,請不吝動動手指,給博主一個小小的贊和收藏 🌻🌻🌻

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/714610.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/714610.shtml
英文地址,請注明出處:http://en.pswp.cn/news/714610.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

網絡編程-編碼與解碼(Protobuf)

編碼與解碼 下面的文字都來自于極客時間 為什么要編解碼呢?因為計算機數據傳輸的是二進制的字節數據 解碼:字節數據 --> 字符串(字符數據) 編碼:字符串(字符數據)–> 字節數據 我們在編…

Python 實現海康機器人工業相機 MV-CS050-10GC 的實時顯示視頻流及拍照功能(實時顯示視頻流同時可以進行拍照)

參考鏈接: https://www.cnblogs.com/HanYork/p/17388506.html https://www.cnblogs.com/miracle-luna/p/16960556.html#5138211 Flask搭建流媒體服務器:使用Flask搭建一個流媒體服務器_multipart/x-mixed-replace; boundaryframe-CSDN博客

公共字段自動填充

在開發中經常面臨對于一些公共字段的賦值。 如在下表中: 如何讓程序自動為我們需要賦值的公共字段進行賦值,避免在業務代碼中重復寫這些公共字段的賦值代碼 如下圖所示: 實現思路: 1.自定義注解AutoFill,用于標識需…

linux環境安裝cuda toolkit

1 全新安裝 如果環境中沒安裝過cuda版本, 這種情況下比較簡單。 直接在https://developer.nvidia.com/cuda-toolkit-archive選擇對應版本下載安裝即可。 如下為安裝cuda toolkit 11.8. 2 環境中已經存在其他版本 這種情況下比較復雜一些。 首先要確認最高支持的…

李沐動手學習深度學習——4.2練習

1. 在所有其他參數保持不變的情況下,更改超參數num_hiddens的值,并查看此超參數的變化對結果有何影響。確定此超參數的最佳值。 通過改變隱藏層的數量,導致就是函數擬合復雜度下降,隱藏層過多可能導致過擬合,而過少導…

Git多人合作的推送流程

多人合作時,使用Git進行代碼推動(push)需要一定的協調和規范,以確保代碼庫的整體健康。以下是一個常見的多人合作時的Git代碼推動流程: 同步主分支: 在推送之前,確保你的本地主分支(…

【Java】四大函數式接口

消費型接口Consumer 消費型接口接收一個輸入,沒有返回值 在stream流計算中 forEach() 接收一個消費型接口Consumer用于 遍歷元素 /*** 消費型接口* 接收一個輸入,沒有返回值*/ public class demo01 {public static void main(String[] args) {//TODO 消…

【MySQL】表的內連和外連(重點)

表的連接分為內連和外連。 一、內連接 內連接實際上就是利用 where 子句對兩種表形成的笛卡兒積進行篩選,前面學習的查詢都是內連接,也是在開發過程中使用的最多的連接查詢。 select 字段 from 表1 inner join 表2 on 連接條件 and 其他條件; 注意&…

【數倉】Hadoop集群配置常用參數說明

Hadoop集群中,需要配置的文件主要包括四個 配置核心Hadoop參數: 編輯core-site.xml文件,設置Hadoop集群的基本參數,如文件系統、Hadoop臨時目錄等。 配置HDFS參數: 編輯hdfs-site.xml文件,設置HDFS的相關參…

策略開發:EMA如何計算

EMA的計算原理 EMA 是MA(平滑移動平均線)的另一種形式。全名“加權指數移動平均線”。 2/13就是12日移動平均線的平滑因子,他的意思是指:給予新價格 2/13的權重,給予過去的EMA 11/13的權重。 在計算的時候第一天的M…

Linux使用基礎命令

1.常用系統工作命令 (1).用echo命令查看SHELL變量的值 qiangziqiangzi-virtual-machine:~$ echo $SHELL /bin/bash(2).查看本機主機名 qiangziqiangzi-virtual-machine:~$ echo $HOSTNAME qiangzi-virtual-machine (3).date命令用于顯示/設置系統的時間或日期 qiangziqian…

Linux多線程服務端編程:使用muduo C++網絡庫 學習筆記 附錄B 從《C++ Primer(第4版)》入手學習C++

這是作者為《C Primer(第4版)(評注版)》寫的序言,文中“本書”指的是這本書評注版。 B.1 為什么要學習C 2009年本書作者Stanley Lippman先生應邀來華參加上海祝成科技舉辦的C技術大會,他表示人們現在還用…

MySQL存儲過程和Function

一、存儲過程 MySQL中提供存儲過程和存儲函數機制,將其統稱為存儲程序。 SQL語句要先編譯,然后執行,存儲程序是一組為了完成特定功能的SQL語句,編譯后存到數據庫中。 用戶通過指定存儲程序的名字并給定參數來調用才會執行。 存…

擴展學習|大數據分析的現狀和分類

文獻來源:[1] Mohamed A , Najafabadi M K , Wah Y B ,et al.The state of the art and taxonomy of big data analytics: view from new big data framework[J].Artificial Intelligence Review: An International Science and Engineering Journal, 2020(2):53. 下…

藍橋杯(3.2)

1209. 帶分數 import java.io.*;public class Main {static BufferedReader br new BufferedReader(new InputStreamReader(System.in));static PrintWriter pw new PrintWriter(new OutputStreamWriter(System.out));static final int N 10;static int n, cnt;static int[…

LabVIEW流量控制系統

LabVIEW流量控制系統 為響應水下航行體操縱舵翼環量控制技術的試驗研究需求,通過LabVIEW開發了一套小量程流量控制系統。該系統能夠滿足特定流量控制范圍及精度要求,展現了其在實驗研究中的經濟性、可靠性和實用性,具有良好的推廣價值。 項…

tritonserver學習之八:redis_caches實踐

tritonserver學習之一:triton使用流程 tritonserver學習之二:tritonserver編譯 tritonserver學習之三:tritonserver運行流程 tritonserver學習之四:命令行解析 tritonserver學習之五:backend實現機制 tritonserv…

【C++初階】內存管理

目錄 一.C語言中的動態內存管理方式 二.C中的內存管理方式 1.new/delete操作內置類型 2.new和delete操作自定義類型 3.淺識拋異常 (內存申請失敗) 4.new和delete操作自定義類型 三.new和delete的實現原理 1.內置類型 2.自定義類型 一.C語…

C++學習筆記:二叉搜索樹

二叉搜索樹 什么是二叉搜索樹?搜索二叉樹的操作查找插入刪除 二叉搜索樹的應用二叉搜索樹的代碼實現K模型:KV模型 二叉搜索樹的性能怎么樣? 什么是二叉搜索樹? 二叉搜索樹又稱二叉排序樹,它或者是一棵空樹,或者是具有以下性質的二叉樹: 若它的左子樹…

Linux安裝Nginx詳細步驟

1、創建兩臺虛擬機,分別為主機和從機,區別兩臺虛擬機的IP地址 2、將Nginx素材內容上傳到/usr/local目錄(pcre,zlib,openssl,nginx) 附件 3、安裝pcre庫   3.1 cd到/usr/local目錄 3.2 tar -zxvf pcre-8.36.tar.gz 解壓 3.3 cd…