mysql锁与事务
2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>
一、RDBMS數(shù)據(jù)組織
RDBMS中數(shù)據(jù)組織涉及到兩個(gè)最基本的結(jié)構(gòu):表與索引。表中存儲(chǔ)的是完整記錄,一般有兩種組織形式:堆表(所有的記錄無序存儲(chǔ),如Oracle/DB2/PostgreSQL),或者是聚簇索引表(所有的記錄,按照記錄主鍵進(jìn)行排序存儲(chǔ),如InnoDB引擎)。索引中存儲(chǔ)的是完整記錄的一個(gè)子集,用于加速記錄的查詢速度,索引的組織形式,一般均為B+樹結(jié)構(gòu)。
二、RDBMS鎖的原則
2PL(二階段鎖Two-Phase Locking):傳統(tǒng)RDBMS加鎖的一個(gè)原則,就是2PL,說的是鎖操作分為兩個(gè)階段:加鎖階段與解鎖階段,并且保證加鎖階段與解鎖階段不相交。下面以MySQL為例,來簡單看看2PL在MySQL中的實(shí)現(xiàn)。
從上圖可以看出,2PL就是將加鎖/解鎖分為兩個(gè)完全不相交的階段。加鎖階段:只加鎖,不放鎖。解鎖階段:只放鎖,不加鎖。所以JDBC Connection需要通過commit/rollback來提交或者釋放鎖。
三、MVCC
MySQL是一個(gè)支持插件式存儲(chǔ)引擎的數(shù)據(jù)庫系統(tǒng)。不同引擎的表現(xiàn),會(huì)有較大的區(qū)別。InnoDB存儲(chǔ)引擎實(shí)現(xiàn)的是基于多版本的并發(fā)控制協(xié)議——MVCC (Multi-Version Concurrency Control) (注:與MVCC相對(duì)的,是基于鎖的并發(fā)控制,Lock-Based Concurrency Control)。
MVCC最大的好處,讀不加鎖,讀寫不沖突。在讀多寫少的OLTP應(yīng)用中,讀寫不沖突是非常重要的,極大的增加了系統(tǒng)的并發(fā)性能,這也是為什么現(xiàn)階段,幾乎所有的RDBMS,都支持了MVCC。
在MVCC并發(fā)控制中,讀操作可以分成兩類:快照讀 (snapshot read)與當(dāng)前讀 (current read)。快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。當(dāng)前讀,讀取的是記錄的最新版本,并且,當(dāng)前讀返回的記錄,都會(huì)加上鎖,保證其他事務(wù)不會(huì)再并發(fā)修改這條記錄。
四、InnoDB一級(jí)索引、二級(jí)索引
每個(gè)InnoDB表具有一個(gè)特殊的索引稱為聚簇索引(也叫聚集索引,聚類索引,簇集索引)。如果表上定義有主鍵,該主鍵索引就是聚簇索引。如果未定義主鍵,MySQL取第一個(gè)唯一索引(unique)而且只含非空列(NOT NULL)作為主鍵,InnoDB使用它作為聚簇索引。如果沒有這樣的列,InnoDB就自己產(chǎn)生一個(gè)這樣的ID值,它有六個(gè)字節(jié),而且是隱藏的,使其作為聚簇索引。
表中的聚簇索引(clustered index )就是一級(jí)索引,除此之外,表上的其他非聚簇索引都是二級(jí)索引,又叫輔助索引(secondary indexes)
五、Mysql鎖
5.1、鎖的分類:
1、共享鎖(S鎖、讀鎖):允許并發(fā)的讀取同一資源, 但會(huì)阻塞其他寫鎖的sql請(qǐng)求;
2、排他鎖(X鎖、寫鎖):一個(gè)寫鎖會(huì)阻塞其他的寫鎖或讀鎖,保證同一時(shí)刻只有一個(gè)連接可以寫入數(shù)據(jù)。
recordLock(行鎖):直接加在索引記錄上面,鎖住的是key,而非記錄本身(Oracle是通過在數(shù)據(jù)塊中對(duì)相應(yīng)數(shù)據(jù)行加鎖來實(shí)現(xiàn)的)。如果該表上沒有任何索引,那么Innodb會(huì)在后臺(tái)創(chuàng)建一個(gè)隱藏的聚簇索引,鎖住的就是這個(gè)隱藏的聚簇索引。即當(dāng)一條sql沒有走任何索引時(shí),那么將會(huì)在每一條聚簇索引后面加X鎖,這個(gè)類似于表鎖,但原理上和表鎖應(yīng)該是不同的。為了效率考量,MySQL做了優(yōu)化,對(duì)于不滿足條件的記錄,會(huì)在判斷后放鎖,最終持有的,是滿足條件的記錄上的鎖,但是不滿足條件的記錄上的加鎖/放鎖動(dòng)作不會(huì)省略。
gapLock(間隙鎖):鎖定索引記錄間隙,確保索引記錄的間隙不變。間隙鎖是針對(duì)事務(wù)隔離級(jí)別為可重復(fù)讀或以上的。
next key lock:recordLock+gapLock
5.2、鎖的策略
1、row lock(行鎖):表中某些行被某個(gè)連接占用了寫鎖,但是其他行依然可以被其他連接請(qǐng)求讀鎖、寫鎖。
2、table lock(表鎖):整個(gè)表被某一個(gè)連接占用了寫鎖,導(dǎo)致其他連接的讀鎖或者寫鎖都會(huì)阻塞;影響整個(gè)表的讀寫。通常發(fā)生在DDL語句\DML不走索引的語句中。
六、Sql分析
select * from table where xxx; (MVCC快照讀,一般不加鎖)
select * from table where xxx lock in share mode;? (讀鎖,當(dāng)前讀,顯示鎖,會(huì)阻塞其他的寫鎖請(qǐng)求,但其他的讀鎖請(qǐng)求沒有影響)
select * from table where xxx for update;? (寫鎖,當(dāng)前讀,顯示鎖,會(huì)阻塞其他的讀寫請(qǐng)求,)
update tableName set xxx (寫鎖,當(dāng)前讀,隱式鎖)
insert (寫鎖,當(dāng)前讀,隱式鎖)
delete (寫鎖,當(dāng)前讀,隱式鎖)
說明:為什么將插入/更新/刪除操作,都?xì)w為當(dāng)前讀?可以看看下面這個(gè)更新操作,在數(shù)據(jù)庫中的執(zhí)行流程:
一個(gè)Update操作的具體流程:當(dāng)Update SQL被發(fā)給MySQL后,MySQL Server會(huì)根據(jù)where條件,讀取第一條滿足條件的記錄,然后InnoDB引擎會(huì)將第一條記錄返回,并加鎖 (current read)。待MySQL Server收到這條加鎖的記錄之后,會(huì)再發(fā)起一個(gè)Update請(qǐng)求,更新這條記錄。一條記錄操作完成,再讀取下一條記錄,直至沒有滿足條件的記錄為止。因此,Update操作內(nèi)部,就包含了一個(gè)當(dāng)前讀。同理,Delete操作也一樣。Insert操作會(huì)稍微有些不同,簡單來說,就是Insert操作可能會(huì)觸發(fā)Unique Key的沖突檢查,也會(huì)進(jìn)行一個(gè)當(dāng)前讀。
注:根據(jù)上圖的交互,針對(duì)一條當(dāng)前讀的SQL語句,InnoDB與MySQL Server的交互,是一條一條進(jìn)行的,因此,加鎖也是一條一條進(jìn)行的。先對(duì)一條滿足條件的記錄加鎖,返回給MySQL Server,做一些DML操作;然后在讀取下一條加鎖,直至讀取完畢。
七、Mysql事務(wù)
ANSI/ISO SQL標(biāo)準(zhǔn)定義了4中事務(wù)隔離級(jí)別:讀未提交(read uncommitted),讀提交(read committed),重復(fù)讀(repeatable read),串行讀(serializable)。不同的隔離級(jí)別有不同的現(xiàn)象:
1、臟讀(dirty read):一個(gè)事務(wù)可以讀取另一個(gè)尚未提交事務(wù)的修改數(shù)據(jù)。
2、不可重復(fù)讀(nonrepeatable read):在同一個(gè)事務(wù)中,同一個(gè)查詢?cè)赥1時(shí)間讀取某一行,在T2時(shí)間重新讀取這一行時(shí)候,這一行的數(shù)據(jù)已經(jīng)發(fā)生修改,可能被更新了(update),也可能被刪除了(delete)。
3、幻像讀(phantom read):在同一事務(wù)中,同一查詢多次進(jìn)行時(shí)候,由于其他插入操作(insert)的事務(wù)提交,導(dǎo)致每次返回不同的結(jié)果集。
不同的隔離級(jí)別有不同的現(xiàn)象,并有不同的鎖定/并發(fā)機(jī)制,隔離級(jí)別越高,數(shù)據(jù)庫的并發(fā)性就越差。在Oracle中默認(rèn)的事務(wù)隔離級(jí)別是提交讀(read committed)。對(duì)于MySQL的Innodb的默認(rèn)事務(wù)隔離級(jí)別是重復(fù)讀(repeatable read),Mysql中的RR不會(huì)臟讀、可重復(fù)讀(Innodb使用多版本一致性讀來實(shí)現(xiàn)),并不能完全避免幻讀(這點(diǎn)和ANSI/ISO SQL標(biāo)準(zhǔn)定義的有所區(qū)別),需要加next key locks,可以使顯示鎖(select * for update or lock in share mode)。
?
Ref:
http://hedengcheng.com/?p=771
http://hedengcheng.com/?p=577
https://blog.csdn.net/lemon89/article/details/51477497
https://juejin.im/post/5ab5e44a6fb9a028c97a013d
轉(zhuǎn)載于:https://my.oschina.net/u/3787772/blog/1932688
總結(jié)
- 上一篇: EIGRP协议邻居详解及故障实战分析
- 下一篇: Centos:mysql的安装和使用:y