久久精品人人爽,华人av在线,亚洲性视频网站,欧美专区一二三

MySQL數據庫鎖如何實現

198次閱讀
沒有評論

共計 4176 個字符,預計需要花費 11 分鐘才能閱讀完成。

這篇“MySQL 數據庫鎖如何實現”文章的知識點大部分人都不太理解,所以丸趣 TV 小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“MySQL 數據庫鎖如何實現”文章吧。

1. 什么是鎖

鎖,其實就是一個內存種的結構,在事務還沒有來之前是沒有鎖存在的。在事務未開始前只有一條記錄,是沒有鎖和記錄之間的關聯關系的。

鎖結構種有很多的信息,主要的有兩個:

trx 信息:代表這個鎖結構是哪個事務生成的。

is_waiting:代表當前事務是否在等待。

當一條事務想要對某條記錄進行改動時,就會生成一把鎖,在生成鎖的時候,會去檢查該條記錄有沒有被其他的鎖關聯。① 如果沒有,is_wating 就是 false,不需要等待,此時表示事務上鎖成功,可以進行后續操作;② 如果有其他事務上鎖,則 is_wating 就是 true,加鎖失敗,需要等待其他事務釋放鎖,才能后續操作該記錄。

2. 鎖解決的問題

數據庫鎖主要解決并發情況下,數據隔離問題。數據庫是可以有多個客戶端連接并訪問的,這種情況就會有并發操作同一數據記錄的情況。因此數據庫出現了鎖機制,解決各種并發情況下出現的隔離問題。

3. 并發訪問相同記錄的幾種情況

讀 - 讀:多個事務同事對數據庫的同一條記錄進行讀操作,這種情況對數據庫的記錄沒有發生變化,不會出現什么問題,這種情況不需要解決什么問題。

寫 - 寫:多個事務同事對數據庫的同一條記錄進行寫操作,這種情況會發生臟寫問題,不管那種隔離級別,都不允許這種情況的發生。所有有多個未提交的事務去操作同一條記錄時,需要讓其他事務處于阻塞排隊等待。

讀 - 寫 / 寫 - 讀:在多并發操作同個數據記錄時,有的事務在讀,有的事務在進行寫操作,這種情況會出現臟讀、不可重復讀、幻讀等情況。MySQL 在 repeatable read 隔離級別上,已經解決了幻讀的問題。

4. 理解讀鎖和寫鎖

對于 MySQL 的 innoDB 存儲引擎來說,讀鎖 / 寫鎖可以作用在表上,也可以作用在行上

4.1 讀鎖

讀鎖(S)也稱共享鎖,在多個事務共同讀同一個記錄時,是可以同時讀取,互不影響,互不干擾的。
在進行 SELECT 查詢操作的時候,可以使用讀鎖,使多個任務之間可以共同讀取同一條記錄。但在查詢操作時,也可以使用寫鎖,后面講寫鎖的時候再說。
如何在讀取的時候加鎖:

SELECT * FROM student LOCK IN SHARE MODE;
SELECT * FROM student FOR SHARE;#(mysql 8.0 新寫法)

4.2 寫鎖

寫鎖(X)也稱排他鎖,在事務在進行寫操作時,會上 X 鎖,導致當前事務未完成寫操作時,其他事務的讀 / 寫會被阻塞。保證在同一個時間內,只有一個事務能對事務進行讀 / 寫操作。

在進行讀操作的時候,也可以給記錄加 X 鎖,防止在讀取記錄的時候,其他事務對當前記錄進行更新。

查詢語句加上 X 鎖有,其他事務不能再給該記錄加 S 鎖或 X 鎖。其他事務會阻塞,知道當前事務釋放 X 鎖。

給查詢操作加 X 鎖:

SELECT * FROM student FOR UPDATE;

進行寫操作時,會自動給該條記錄加 X 鎖。寫記錄:INSERT\DELETE\UPDATE 4.3 讀鎖和寫鎖的兼容情況

5. 表鎖

表鎖是指給所操作的整張表進行加鎖,相對行鎖,對表加鎖的顆粒度比較大,因此它的開銷也比較小。由于是對整張數據表進行加鎖,因此可以避免死鎖的出現。即使這樣,是對整張表進行加鎖,就會導致大量的事務無法繼續操作表,所有表鎖的性能是較差的。
在 MySQL 中,InnoDB 提供了表鎖和行鎖由于表鎖的性能比較差,一般我們都很少用到表鎖。只有特殊場景下會用到表鎖,比如:數據崩潰恢復。

5.1 表級的讀 / 寫鎖

對表加 S 鎖:MySQL 的 InnoDB 對整個表加 S 鎖。

對表加 X 鎖:MySQL 的 InnoDB 對整個表加 X 鎖。

查看有那些表被加鎖:

SHOW OPEN TABLES;
SHOW OPEN TABLES WHERE In_use 

手動給表加鎖:

LOCK TABLES student READ;# 給 student 表加 S 鎖
LOCK TABLES stdent WRITE;# 給 student 表加 X 鎖

釋放鎖:

UNLOCK TABLES;

小結

5.2 意向鎖

MySQL 的 InnoDB 存儲引擎中,支持表鎖和行鎖同時存在,而意向鎖就是表鎖的一種。

意向鎖是為了協調表鎖和行鎖同時共存而存在的。意向鎖是一中不于行鎖沖突的表級鎖。意向鎖用戶是無法手動添加的,它是 InnoDB 存儲引擎自動給加的。當在給某個行添加 S 鎖或 X 鎖時,需要先獲取當前行所在表的意向鎖。

意向鎖分為兩種:

意向共享鎖(IS):事務有意向對表中的某行加共享鎖(S 鎖)。當給某一行記錄加了共享鎖(S)后,數據庫就會給當前的數據表或數據頁加上意向共享鎖,當想給當前表加入一個排他鎖 (X) 時,就會檢測到意向共享鎖,就會被排斥阻塞,不能加鎖。但是加表的共享鎖時,是可以的。

意向排他鎖(IX):事務有意向對表中的某行加排他鎖(X 鎖)。當給某一行記錄加了排他鎖(X)后,數據庫就會給當前的數據表或數據頁加上意向排他鎖,當想給當前表加入一個排他鎖 (X) 或者意向鎖 (S) 時,就會檢測到意向排他鎖,就會被排斥阻塞,不能加鎖。

理解意向鎖的意義:當沒有意向鎖的時候,當事務想要給表加表鎖的時候,需要去檢測每行記錄是否加有鎖,這樣每條檢測的效率非常的低。意向鎖的出現,很好的解決這種情況。有意向鎖后,事務要表添加鎖,只要檢查當前表是否有意向鎖就可以了。

總結:意向鎖之間是互相兼容的和讀寫鎖不兼容:

6. 行鎖

行鎖就是給表中的某條記錄上把鎖,將該條記錄鎖住。行鎖是在 InnoDB 存儲引擎層實現的,這是 InnoDB 與 MyISAM 最大的區別之一。行鎖是粒度小的,發生鎖沖突的概率很小,因此會實現高并發的效果,但是因粒度較小,加鎖較慢,會出現死鎖的情況

6.1 記錄鎖

記錄鎖就是一把行鎖,顧名思義,給某條記錄上鎖。

共享記錄鎖(S):當一個事務得到了某個事務的共享鎖后,其他事務還能繼續獲取該記錄的共享鎖,但是不能獲取該記錄的排他鎖。

排他記錄鎖(X):當一個事務得到了某個事務的排他鎖后,其他事務不能獲取該記錄的共享鎖和排他鎖。

6.2 間隙鎖

間隙鎖是在某個記錄前的間隙加入一個鎖,這樣就使該記錄前面的間隙是不能添加數據的。這種間隙鎖有效的防止了幻讀的出現。間隙鎖的出現,也是為了解決幻讀而提出來的。
不管是共享鎖還是排他鎖,起到的作用是一樣的,
舉例:

select * from student where id=11 for update;

此時 id 為 18 加了間隙鎖

這種會出現一個問題,因為間隙鎖只會鎖住行前面的間隙,那么,如果此時給 id 為 25 后面的間隙插入數據,就會有問題,此時,數據庫做了兩個提供了兩個偽記錄:Infimum 記錄,表示該頁面中最小的記錄。Supremun 記錄,表示該頁面中最大的記錄。
加入如下,就可以阻止其他事務加入(25,+ infin;)的數據了。

select * from student where id   20 lock in share mode;

間隙鎖的出現,會發生死鎖,如下:

當記錄中存在間隙鎖時,有其他事務想在這個間隙插入數據,由于鎖的存在,會阻止插入,讓事務進行等待,知道釋放間隙鎖。此時內存中會生成一個插入意向鎖,這個意向鎖是一種間隙鎖,并不是表鎖中的意向鎖。這種插入意向鎖可以有多個,一個間隙中有多個插入意向鎖并不沖突,插入意向鎖之間不會有排斥。

6.3 臨界鎖

臨界鎖是用來補充上面說的間隙鎖,因為間隙鎖只是鎖住了記錄前面的間隙,但是并不包含自己,因此臨界鎖就出現了,臨界鎖就是記錄鎖和間隙鎖的組合體。

select * from student where id  =18 and id   10 for update;

7. 悲觀鎖和樂觀鎖

悲觀鎖、樂觀鎖其實并不是一種鎖,而是一中并發下鎖的一種設計思想

7.1 悲觀鎖

悲觀鎖,就是很悲觀,對數據被其他事務操作的時候,保持悲觀態度。總是認為數據會被其他事務修改,所以每次操作數據的時候,都會被數據上鎖,使別他事務操作數據的時候處于阻塞狀態,知道釋放鎖,保證數據具有排他性。

行鎖、表鎖、讀鎖、寫鎖就是悲觀鎖的體現,每次在操作數據的時候,都會加鎖,使其他數據在訪問的時候被阻塞掛起,直到釋放鎖。

其實悲觀鎖的使用場景并不是很多,因為它在每次操作的時候,都會給數據上鎖,這樣會在事務比較長的時候,性能會比較差。

悲觀鎖的適用場景是寫操作多的情況下,因為寫具有排他性,在寫操作的時候,阻止其他事務對數據的讀或寫的操作,這樣很大的避免了讀 - 寫 / 寫 - 讀的沖突,進而避免了臟讀、不可重復讀、幻讀的問題。

7.2 樂觀鎖

樂觀鎖,就是對數據的操作持有樂觀的態度,任務每次操作數據時,都不會有其他的事務對數據進行修改操作。但是在每次一修改數據的時候,都會判斷在此期間數據是否被其他事務修改過。

樂觀鎖是在操作數據的時候,通過程序來進行控制的,比如:使用版本號,或者時間戳來進行比對。

版本號的樂觀鎖:在數據表中,添加一個字段 rsquo;version rsquo;,這個字段使用來記錄每次數據跟新后的數據版本。在進行數據的更新操作時,會先拿到 rsquo;version rsquo; 字段的值,更新數據的時候,會拿之前的 version 的值和現在數據庫里面的 lsquo;version rsquo; 進行比較,如果兩個 lsquo;version rsquo; 的值是一樣的,說明在此期間數據沒有被修改過,可以進行更新操作。反過來,如果兩個 lsquo;version rsquo; 的值不一樣,說明此期間有其他事務修改過這條記錄,則更新失敗。

在更新數據的時候,會使 rsquo;version rsquo; 的值加 1。

`UPDATE student SET name=  李四  ,version=version+1 WHERE version=version`

樂觀鎖的適用場景讀多寫少的場景,由程序實現,不會出現死鎖問題。

以上就是關于“MySQL 數據庫鎖如何實現”這篇文章的內容,相信大家都有了一定的了解,希望丸趣 TV 小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注丸趣 TV 行業資訊頻道。

正文完
 
丸趣
版權聲明:本站原創文章,由 丸趣 2023-07-13發表,共計4176字。
轉載說明:除特殊說明外本站除技術相關以外文章皆由網絡搜集發布,轉載請注明出處。
評論(沒有評論)
主站蜘蛛池模板: 红桥区| 龙山县| 辛集市| 吴桥县| 荥经县| 康定县| 鹤庆县| 宜兴市| 萨迦县| 宾川县| 宜春市| 霍林郭勒市| 三门峡市| 青河县| 柏乡县| 巴彦淖尔市| 镇安县| 樟树市| 万山特区| 黄浦区| 元朗区| 汤原县| 抚州市| 黎川县| 福清市| 定州市| 台湾省| 固原市| 济阳县| 佳木斯市| 柏乡县| 赤水市| 平定县| 榕江县| 天祝| 辽中县| 进贤县| 铜山县| 洛阳市| 邹城市| 遂溪县|