日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

mysql锁的一些理解简书_MySQL锁系列之锁的种类和概念

發(fā)布時(shí)間:2025/3/21 数据库 75 豆豆
生活随笔 收集整理的這篇文章主要介紹了 mysql锁的一些理解简书_MySQL锁系列之锁的种类和概念 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

在mysql當(dāng)中,關(guān)于innodb的鎖類型總共可以分為四種,包含了行鎖和表鎖,分別是

基本鎖 - [ 共享鎖(Shared Locks:S鎖)和排它鎖(Exclusive Locks:X鎖)]

意向鎖 - [ intention lock,分為意向共享鎖(IS鎖)和意向排他鎖(IX鎖)]

行鎖 - [ record Locks、gap locks、next-key locks、Insert Intention Locks ]

自增鎖 - [ auto-inc locks ]

下面是各種鎖之間的對應(yīng)兼容情況(ps:在某一篇博客上看到,忘了是哪一篇,覺得好就截下來了嘻嘻):

InnoDB三種行鎖的算法:

Record Lock:單個(gè)行記錄上的鎖,只鎖定記錄本身

Gap Lock:間隙鎖,鎖定一個(gè)范圍,但不包括記錄本身。 目的是為了防止同一個(gè)事物的兩次當(dāng)前讀,出現(xiàn)幻讀的情況

Next-Key Lock:1+2,鎖定一個(gè)范圍,并鎖定記錄本身。目的:解決幻讀

共享鎖

共享鎖shared locks(S鎖)也稱讀鎖,允許其他事物再加S鎖,不允許其他事物再加X鎖

加鎖方式:

select...lock in share mode

注意:

對于使用共享鎖的事務(wù),其他事務(wù)只能讀,不可寫

如果執(zhí)行了更新操作則會(huì)一直等待,直到當(dāng)前事務(wù)commit或者rollback

如果當(dāng)前事務(wù)也執(zhí)行了其他事務(wù)處于等待的那條sql語句,當(dāng)前事務(wù)將會(huì)執(zhí)行成功,而其他事務(wù)會(huì)報(bào)死鎖

并且允許其他鎖共存

排它鎖

排它鎖Exclusive Locks(X鎖)也稱寫鎖,不允許其他事務(wù)再加S鎖或者X鎖

加鎖方式:

select ... for update

→ for update:InnoDB默認(rèn)是行級(jí)別的鎖,當(dāng)有明確指定的主鍵時(shí),使用的是行鎖;否則使用的是表鎖。使用情況詳細(xì)如下:

明確指定主鍵,并且由此記錄,行級(jí)鎖。例:

select name,age from tb_user where id = '1' for update(id是主鍵)

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

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

無主鍵/索引,表級(jí)鎖。例:

select name,age from tb_user where age = 12 for update(age是普通字段)

主鍵/索引不明確,表級(jí)鎖。例:

select name,age from tb_user where age = 12,id = '1' for update(id是主鍵,age不是,但數(shù)據(jù)庫有此數(shù)據(jù))

注意:

對于排它鎖的事務(wù),其他事物可讀,但不可進(jìn)行更新操作

for update僅使用與InnoDB,并且必須開啟事務(wù),在begin和commit之間才生效

當(dāng)一個(gè)事務(wù)進(jìn)行for update的時(shí)候,另一個(gè)事務(wù)也有for update時(shí)會(huì)一直等待,直到之前的事務(wù)commit或rollback或斷開連接釋放鎖才拿到鎖進(jìn)行后面的操作(排它鎖不能共存)

innoDB引擎.默認(rèn)對update,delete,insert加排他鎖,select語句默認(rèn)不加鎖

樂觀鎖

讀取出記錄,并將此版本一同讀出,執(zhí)行更新操作并對記錄的版本號(hào)+1。此時(shí),將待提交記錄的版本號(hào)與數(shù)據(jù)庫對應(yīng)表的記錄版本好進(jìn)行對比,如果大于數(shù)據(jù)庫原有版本號(hào)的話,予以更新;否則認(rèn)為是過期數(shù)據(jù),更新失敗。目的是為了用于解決并發(fā)問題。

例:A、B兩個(gè)人同時(shí)修改同一條記錄,設(shè)數(shù)據(jù)庫原有金額是100元,A對金額+100,B往數(shù)據(jù)庫-50,正常結(jié)果是150,但由于并發(fā),結(jié)果有可能是200,或者50

解決:A B同時(shí)讀取出數(shù)據(jù)版本為1,A對金額+100,并修改數(shù)據(jù)版本為2,提交數(shù)據(jù),此時(shí)數(shù)據(jù)版本為1,更新成功。B讀取數(shù)據(jù)版本1,對金額-50,此時(shí)結(jié)果為50,并修改數(shù)據(jù)版本為2,提交數(shù)據(jù),對比數(shù)據(jù)庫原版本2,沒有比原版本高,更新失敗

間隙鎖

間隙鎖是在索引記錄之間的間隙的鎖定,或在最后一個(gè)索引記錄之前或之后的間隙上的鎖定

使用唯一索引搜索唯一一行的一句不需要間隙鎖鎖定(不包括搜索條件包含多列唯一索引的某些列的情況,查詢出的多條記錄,會(huì)發(fā)生間隙索引),詳細(xì)例子如下:

前提:(id是主鍵索引)由于搜索結(jié)果是唯一的一條記錄,所以不會(huì)使用間隙鎖

select id,name,age from tb_user where id = '1'

前提:(id是主鍵索引、age是非索引字段)由于搜索結(jié)果可能不止一條記錄,所以會(huì)使用間隙鎖select id,name,age from tb_user where id = '1' and age = 13

演示:

→ 數(shù)據(jù)結(jié)構(gòu):

CREATE TABLE `tb_user` (

`id` int(10) NOT NULL,

`name` varchar(255) NOT NULL DEFAULT '',

KEY `index_id` (`id`),

KEY `index_name` (`name`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8

→ 初始化數(shù)據(jù):

ps:我現(xiàn)在使用的是數(shù)據(jù)庫默認(rèn)的隔離級(jí)別:repeatable read,并在本地開啟兩個(gè)客戶端進(jìn)行測試。

→ 客戶端1:開啟事務(wù),在客戶端中修改id為1-6之間的數(shù)據(jù),此時(shí)id=2這行記錄是不存在的

→ 客戶端2:開啟事務(wù),往數(shù)據(jù)庫中添加id為2的記錄時(shí)會(huì)發(fā)現(xiàn)該操作會(huì)被阻塞!

-->上述情況就說明了有間隙鎖的存在

--> 接下來我修改了隔離級(jí)別為read commited,可以發(fā)現(xiàn)上述添加操作,即id =2 的記錄會(huì)添加成功,說明read commited的隔離級(jí)別不會(huì)使用間隙鎖。

注意:

間隙鎖在InnoDB的唯一作用就是防止其它事務(wù)的插入操作,以此來達(dá)到防止幻讀的發(fā)生,所以間隙鎖不分什么共享鎖與排它鎖。

如果InnoDB掃描的是一個(gè)主鍵/唯一索引,那么InnoDB只會(huì)采用行鎖(Record Lock)方式來加鎖,而不會(huì)使用間隙鎖(Next-Key Lock)的方式。

間隙鎖只是阻止其他事物插入到間隙當(dāng)中,并不阻止不同的事物在同一間隙上獲得間隙鎖。

將隔離級(jí)別設(shè)置為read_commited或啟用innodb_locks_unsafe_for_binlog系統(tǒng)變量(現(xiàn)已被棄用)可明確禁止使用間隙鎖

MVCC(Snapshot read vs current read)

MVCC,基于多版本的并發(fā)控制協(xié)議,最典型的是讀不加鎖,讀寫不沖突,其包含兩種讀操作,即快照讀(snapshot read)與當(dāng)前讀(current read)。

快照讀:讀取記錄的可見版本,不加鎖。

當(dāng)前讀:讀取記錄的最新版本,當(dāng)前讀返回的記錄,都會(huì)加鎖,保證其他事物不會(huì)再修改這條記錄

那具體哪些操作為當(dāng)前讀,哪些操作又是快照讀呢,讓我們來看一下:

→ 快照讀:簡單的讀操作,屬于快照讀,不加鎖。(不過有些會(huì)有點(diǎn)小例外)

例:select * from tb_user where ?

→ 當(dāng)前讀:特殊的讀操作,屬于當(dāng)前讀,需要加鎖。

select * from table where ? lock in share mode;

select * from table where ? for update;

insert into table values (…);

update table set ? where ?;

delete from table where ?;

所有以上的語句,都屬于當(dāng)前讀,讀取記錄的最新版本。并且,讀取之后,還需要保證其他并發(fā)事務(wù)不能修改當(dāng)前記錄,對讀取記錄加鎖。其中,除了第一條語句,對讀取記錄加S鎖 (共享鎖)外,其他的操作,都加的是X鎖 (排它鎖)。

總結(jié)

以上是生活随笔為你收集整理的mysql锁的一些理解简书_MySQL锁系列之锁的种类和概念的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。