mysql锁的一些理解简书_MySQL锁系列之锁的种类和概念
在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)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: down 网卡端口周期性的up_down
- 下一篇: linux无法访问mysql_Linux