欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Mysql鎖之共享鎖(讀鎖)和排他鎖(寫鎖)詳解

 更新時間:2023年07月27日 09:55:40   作者:煙雨樓臺笑江湖  
這篇文章主要介紹了Mysql鎖之共享鎖(讀鎖)和排他鎖(寫鎖),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

InnoDB和MyISAM

Mysql在5.5之前默認使用MyISAM存儲引擎,之后使用InnoDB。

查看當前存儲引擎:

show variables like ‘%storage_engine%';

MyISAM操作數(shù)據(jù)都是使用的表鎖,你更新一條記錄就要鎖整個表,導致性能較低,并發(fā)不高。當然它也不會存在死鎖問題。

InnoDB與M有ISAM的最大不同有兩點

  • InnoDB支持事務
  • InnoDB采用了行級鎖。也就是你需要修改哪行,就可以只鎖定哪行。

在Mysql中,行級鎖并不是直接鎖記錄,而是鎖索引。

索引分為主鍵索引和非主鍵索引兩種,如果一條sql語句操作了主鍵索引,Mysql就會鎖定這條主鍵索引;如果一條語句操作了非主鍵索引,Mysql會先鎖定該非主鍵索引,再鎖定相關(guān)的主鍵索引。

InnoDB行鎖是通過給索引加鎖實現(xiàn)的,如果沒有索引,InnoDB會通過因此的聚簇索引來對記錄加鎖。

也就是說:如果不通過索引條件檢索數(shù)據(jù),那么InnoDB將對表中所有數(shù)據(jù)加鎖,實際效果跟表鎖一樣。因為沒有了索引,找到記錄就得掃描全表,要掃描全表,就得鎖定表。

共享鎖與排他鎖

首先說明:InnoDB引擎默認對update,delete,insert加排它鎖,select語句默認不加鎖

共享鎖

共享鎖shared locks(S鎖)也稱讀鎖:用于不更改或不更新數(shù)據(jù)的操作(只讀操作),可以查看但無法修改和刪除的一種數(shù)據(jù)鎖,如select語句。

如果事務T對數(shù)據(jù)A加上共享鎖后,則其他事務只能對數(shù)據(jù)A再加共享鎖,不能加排他鎖。獲準共享鎖的事務只能讀數(shù)據(jù),不能修改數(shù)據(jù)。共享鎖下其它用戶可以并發(fā)讀取,查詢數(shù)據(jù)。但不能修改,增加,刪除數(shù)據(jù)。資源共享。

加鎖方式

select ... lock in share mode

注意:

  • 對于使用共享鎖的事務,其他事務只能讀,不可寫
  • 如果執(zhí)行了更新操作則會一直等待,直到當前事務commit或者rollback
  • 如果當前事務也執(zhí)行了其他事務處于等待的那條sql語句,當前事務將會執(zhí)行成功,而其他事務會報死鎖
  • 允許其他鎖共存

排它鎖

排它鎖Exclusive Locks(X鎖)也稱寫鎖、獨占鎖:用于數(shù)據(jù)修改操作,例如insert、update或delete。確保不會同時對同一資源進行多重更新。

如果事務T對數(shù)據(jù)A加上排它鎖后,則其他事務不能在對A加任何類型的鎖。獲準排他鎖的事務既能讀數(shù)據(jù),又能修改數(shù)據(jù)。我們在操作數(shù)據(jù)庫的時候,可能會由于并發(fā)問題而引起的數(shù)據(jù)的不一致性(數(shù)據(jù)沖突)

加鎖方式

select ... for update

**for update:**InnoDB默認是行級別的鎖,當有明確指定的主鍵是,使用的是行鎖;否則使用表鎖。使用情況詳細如下:

明確指定主鍵,并且存在此記錄,行級鎖。例如:

-- id是主鍵
select name,age from table_user where id = '1' for update;

明確指定主鍵,若查無記錄,無鎖。例如:

-- id是主鍵,單不存在id = 1的數(shù)據(jù)
select name,age from table_user where id = '1' for update;

無主鍵,表級鎖。例如:

-- age是普通字段
select name,age from table_user where age = 12 for update;

主鍵不明確,表級鎖。例如:

-- id是主鍵,age不是,但數(shù)據(jù)庫
select name,age from table_user where age = 12 and id = '1' for update;

注意:

  • 對于排它鎖的事務,其它事務可讀,但不可進行更新操作
  • for update僅使用與InnoDB,并且必須開啟事務,在begin和commit之間才生效
  • 當一個事務進行for update的時候,另一個事務也有for update時會一直等待,直到之前的事務commit或rollback或斷開連接釋放鎖才能拿到鎖進行后面的操作(排它鎖不能共存)
  • InnoDB引擎默認對update,delete,insert加排它鎖,select語句默認不加鎖
  • 加過排他鎖的數(shù)據(jù)行在其他事務中是不能修改數(shù)據(jù)的,也不能通過for update和lock in share mode鎖的方式查詢數(shù)據(jù),但可以直接通過select … from …查詢數(shù)據(jù),因為普通查詢沒有任何鎖機制

樂觀鎖與悲觀鎖

首先說明:樂觀鎖和悲觀鎖都是針對讀(select)來說的。

樂觀鎖

樂觀鎖不是數(shù)據(jù)庫自帶的,需要我們自己去實現(xiàn)。

樂觀鎖是指操作數(shù)據(jù)庫時(更新操作),想法很樂觀,認為這次的操作不會導致沖突,在操作數(shù)據(jù)時,并不進行任何其他的特殊處理(也就是不加鎖),而在進行更新后,再去判斷是否有沖突了。

悲觀鎖

悲觀鎖就是在操作數(shù)據(jù)時,認為此操作會出現(xiàn)數(shù)據(jù)沖突,所以在進行每次操作時都要通過獲取鎖才能進行對相同數(shù)據(jù)的操作,這點跟Java中的synchronized很相似,所以悲觀鎖需要耗費較多的時間。

另外與樂觀鎖相對應,悲觀鎖是由數(shù)據(jù)庫自己實現(xiàn)了的,要用的時候,我們直接調(diào)用數(shù)據(jù)庫的相關(guān)語句就可以了。

由悲觀鎖涉及到的另外兩個鎖概念,就是共享鎖與排他鎖。共享鎖和排他鎖是悲觀鎖的不同實現(xiàn),它倆都屬于悲觀鎖的范疇。

案例

某商品,用戶購買后庫存應-1,而某兩個或多個用戶同時購買,此時三個執(zhí)行程序均同時讀得庫存為“n”,之后進行了一些操作,最后將均執(zhí)行update table set 庫存書 = n - 1,那么,很顯然這是錯誤的。

解決

1.使用悲觀鎖(也就是排他鎖)

  • 程序A在查詢庫存數(shù)時使用排他鎖(select * from table where id = 10 for update)
  • 然后進行后續(xù)操作,包括更新庫存數(shù),最后提交事務
  • 程序B在查詢庫存數(shù)時,如果A還未釋放排他鎖,程序B將等待。。。
  • 程序C同B。。。

2.使用樂觀鎖(靠表設計和代碼來實現(xiàn))

一般是在該商品表添加version版本字段或者timestamp時間戳字段

程序A查詢后,執(zhí)行更新變成了:

update table set num = num - 1 and version = 23

這樣,保證了修改的數(shù)據(jù)是和它查詢出來的數(shù)據(jù)是一致的(其他執(zhí)行程序肯定未進行修改)。當然,如果更新失敗,表示在更新操作之前,有其他執(zhí)行程序已經(jīng)更新了該庫存數(shù),那么就可以嘗試重試來保證更新成功。為了盡可能避免更新失敗,可以合理調(diào)整重試次數(shù)(阿里巴巴開發(fā)手冊規(guī)定重試次數(shù)不低于三次)。

樂觀鎖和悲觀鎖的區(qū)別

悲觀鎖實際使用了排他鎖來實現(xiàn)**(select … for update)**。InnoDB加行鎖的前提是:必須是通過索引條件來檢索數(shù)據(jù),否則會切換為表鎖。

因此,悲觀鎖在未通過索引條件檢索數(shù)據(jù)時,會鎖定整張表。導致其他程序不允許**“加鎖的查詢操作”**,影響吞吐。因此,如果在查詢居多的情況下,推薦使用樂觀鎖。

加鎖的查詢操作:加過排他鎖的數(shù)據(jù)行在其他事務中是不能修改的,也不能通過for update或lock in share mode的加鎖方式查詢,但可以直接通過select … from …查詢數(shù)據(jù),因為普通查詢沒有任何鎖機制。

樂觀鎖更新有可能會失敗,甚至是更新幾次都失敗,這是有風險的。所以如果寫入居多,對吞吐要求不高,可使用悲觀鎖。

結(jié)尾:讀用樂觀鎖,寫用悲觀鎖。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MySQL數(shù)據(jù)庫定時備份的幾種實現(xiàn)方法

    MySQL數(shù)據(jù)庫定時備份的幾種實現(xiàn)方法

    本文主要介紹了MySQL數(shù)據(jù)庫定時備份的幾種實現(xiàn)方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-07-07
  • ubuntu下mysql版本升級到5.7

    ubuntu下mysql版本升級到5.7

    這篇文章主要為大家詳細介紹了ubuntu下mysql版本升級到5.7的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • 詳解mysql中explain的type

    詳解mysql中explain的type

    這篇文章主要介紹了mysql中explain的type的相關(guān)資料,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2020-11-11
  • mysql用戶管理操作實例分析

    mysql用戶管理操作實例分析

    這篇文章主要介紹了mysql用戶管理操作,結(jié)合實例形式分析了mysql用戶管理查看、創(chuàng)建、修改、刪除等相關(guān)操作技巧,需要的朋友可以參考下
    2020-04-04
  • 遠程連接mysql報錯“Host?xxx?is?not?allowed?to?connect?to?this?MySQL?server“簡單解決辦法

    遠程連接mysql報錯“Host?xxx?is?not?allowed?to?connect?to?th

    這篇文章主要給大家介紹了關(guān)于遠程連接mysql報錯“Host?xxx?is?not?allowed?to?connect?to?this?MySQL?server“的解決辦法,文中通過代碼介紹的非常詳細,需要的朋友可以參考下
    2024-07-07
  • MySQL字段類型與Java實體類類型對應轉(zhuǎn)換關(guān)系詳解

    MySQL字段類型與Java實體類類型對應轉(zhuǎn)換關(guān)系詳解

    這篇文章主要介紹了MySQL字段類型與Java實體類類型對應轉(zhuǎn)換關(guān)系,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-06-06
  • MySQL kill指令使用指南

    MySQL kill指令使用指南

    這篇文章主要介紹了MySQL kill指令的使用方法,幫助大家更好的理解和使用MySQL,感興趣的朋友可以了解下
    2020-12-12
  • MySQL高可用解決方案MMM(mysql多主復制管理器)

    MySQL高可用解決方案MMM(mysql多主復制管理器)

    MySQL本身沒有提供replication failover的解決方案,通過MMM方案能實現(xiàn)服務器的故障轉(zhuǎn)移,從而實現(xiàn)mysql的高可用。MMM不僅能提供浮動IP的功能,如果當前的主服務器掛掉后,會將你后端的從服務器自動轉(zhuǎn)向新的主服務器進行同步復制,不用手工更改同步配置
    2017-09-09
  • MySQL復制表常用的四種方式小結(jié)

    MySQL復制表常用的四種方式小結(jié)

    mysql?想必大家比較熟悉了,我們常見的crud??sql想必大家也是手到拈來,但可能會有人不會寫mysql中復制表,所以接下來本文我會介紹四種常用的復制表的方式,需要的朋友可以參考下
    2023-07-07
  • MySQL常用聚合函數(shù)詳解

    MySQL常用聚合函數(shù)詳解

    下面小編就為大家?guī)硪黄狹ySQL常用聚合函數(shù)詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06

最新評論