數(shù)據(jù)庫的事務,鎖,索引--讀mysql技術(shù)內(nèi)幕&高性能mysql筆記

[toc]

1.事務

1.1 隔離級別和特性

事務的特性ACID

  • A Atomicity 原子性 執(zhí)行的完整性,不可拆分
  • C Consistency 一致性 數(shù)據(jù)庫一致性保持不變
  • I Isolation 隔離性 隔離性確保事務并發(fā)執(zhí)行后的系統(tǒng)狀態(tài)與這些事務以某種次序串行執(zhí)行以后的狀態(tài)是等價的。
  • D Durability 持久性 執(zhí)行后結(jié)果存儲

事務隔離級別
可串行化(Serializable):sql中最高的隔離性級別,能夠避免臟讀,幻讀,不可重復讀。代價也相對沉重,會大大影響數(shù)據(jù)庫的性能。

可重復讀(Repeatable read):只允許讀取已提交的數(shù)據(jù),而且在一個事務兩次讀取一個數(shù)據(jù)項期間,其他事務不得更新該數(shù)據(jù)。這種狀態(tài)不能避免幻讀。

已提交讀(Read committed):只允許讀取已提交數(shù)據(jù),但不要求可重復讀。這種狀態(tài)只能避免臟讀。

未提交讀(Read uncommitted):允許讀取未提交的數(shù)據(jù)。這是最低的隔離級別,臟讀,幻讀,不可重復讀都無法避免。

mysql innodb 默認隔離級別 Repeatable read

1.2 事務日志

https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html

https://blog.csdn.net/yu757371316/article/details/81081669
https://liuzhengyang.github.io/2017/04/18/innodb-mvcc/#Redo-log-bin-log-Undo-log

1.redo log通常是物理日志,記錄的是數(shù)據(jù)頁的物理修改,而不是某一行或某幾行修改成怎樣怎樣,它用來恢復提交后的物理數(shù)據(jù)頁(恢復數(shù)據(jù)頁,且只能恢復到最后一次提交的位置。
2.undo用來回滾行記錄到某個版本。undo log一般是邏輯日志,根據(jù)每行記錄進行記錄

事務日志可以幫助提高事務的效率。保證事務的持久性。
寫日志采用追加方式。
數(shù)據(jù)庫重啟和奔潰時可以從redolog慢慢刷會磁盤。

事務恢復策略
A. 進行恢復時,只重做已經(jīng)提交了的事務。
B. 進行恢復時,重做所有事務包括未提交的事務和回滾了的事務。然后通過Undo Log回滾那些
未提交的事務
。 innodb 采用

1.3 事務的相關(guān)操作

1.查看當前會話隔離級別
select @@tx_isolation;
2.查看系統(tǒng)當前隔離級別
select @@global.tx_isolation;
3.設置當前會話隔離級別
set session transaction isolatin level repeatable read;
4.設置系統(tǒng)當前隔離級別
set global transaction isolation level repeatable read;

2.鎖

https://segmentfault.com/a/1190000014133576
https://lanjingling.github.io/2015/10/10/mysql-hangsuo/
https://blog.csdn.net/wushiwude/article/details/76042509
https://www.zhihu.com/question/51513268
https://liuzhengyang.github.io/2017/04/18/innodb-mvcc/
https://sq.163yun.com/blog/article/174660532728422400
https://segmentfault.com/a/1190000012650596

image

2.1 鎖的類型

2.1.1 共享鎖S

允許一個事務去讀一行,阻止其他事務獲得相同的數(shù)據(jù)集的排他鎖。

select ... in share mode

共享鎖就是我讀的時候,你可以讀,但是不能寫。

2.1.2 排他鎖X

允許獲得排他鎖的事務更新數(shù)據(jù),但是組織其他事務獲得相同數(shù)據(jù)集的共享鎖和排他鎖。

select ... for update

排他鎖就是我寫的時候,你不能讀也不能寫。。

2.1.3 意向共享鎖IS

表示事務準備給數(shù)據(jù)行加入共享鎖,也就是說一個數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖

2.1.4 意向排他鎖 IX

表示事務準備給數(shù)據(jù)行加入排他鎖,說明事務在一個數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖。

2.1.5 鎖的兼容+ 意向鎖的意義
image

當一個事務請求的鎖模式與當前的鎖兼容,InnoDB就將請求的鎖授予該事務;反之如果請求不兼容,則該事務就等待鎖釋放。

意向鎖是為了實現(xiàn)多粒度鎖,是數(shù)據(jù)庫自動加持的。

對于意向鎖的理解

意向鎖是一種快速判斷表鎖與之前可能存在的行鎖沖突的機制

事務A鎖住了表中的一行,讓這一行只能讀,不能寫。之后,事務B申請整個表的寫鎖。如果事務B申請成功,那么理論上它就能修改表中的任意一行,這與A持有的行鎖是沖突的。數(shù)據(jù)庫需要避免這種沖突,就是說要讓B的申請被阻塞,直到A釋放了行鎖。數(shù)據(jù)庫要怎么判斷這個沖突呢?step1:判斷表是否已被其他事務用表鎖鎖表step2:判斷表中的每一行是否已被行鎖鎖住。注意step2,這樣的判斷方法效率實在不高,因為需要遍歷整個表。于是就有了意向鎖。在意向鎖存在的情況下,事務A必須先申請表的意向共享鎖,成功后再申請一行的行鎖。在意向鎖存在的情況下,上面的判斷可以改成step1:不變step2:發(fā)現(xiàn)表上有意向共享鎖,說明表中有些行被共享行鎖鎖住了,因此,事務B申請表的寫鎖會被阻塞。

2.2 加鎖機制和思想

2.2.1 樂觀鎖

樂觀鎖會“樂觀地”假定大概率不會發(fā)生并發(fā)更新沖突,訪問、處理數(shù)據(jù)過程中不加鎖,只在更新數(shù)據(jù)時再根據(jù)版本號或時間戳判斷是否有沖突,有則處理,無則提交事務

實踐 偽代碼

select version from xxxxx
......
update xxxxx set version=version+1 where version=#{version}
//更新的時候確保version是之錢讀取的version
2.2.2 悲觀鎖

悲觀鎖會“悲觀地”假定大概率會發(fā)生并發(fā)更新沖突,訪問、處理數(shù)據(jù)前就加排他鎖,在整個數(shù)據(jù)處理過程中鎖定數(shù)據(jù),事務提交或回滾后才釋放鎖;

實踐

select xxx from xxx for update //直接獲取排他鎖

2.3 鎖的粒度

2.3.1 行鎖

行鎖的解釋: 對記錄的鎖
行鎖的劣勢:開銷大;加鎖慢;會出現(xiàn)死鎖
行鎖的優(yōu)勢:鎖的粒度小,發(fā)生鎖沖突的概率低;處理并發(fā)的能力強

2.3.2 表鎖

表鎖的解釋: 對表的鎖
表鎖的優(yōu)勢:開銷??;加鎖快;無死鎖
表鎖的劣勢:鎖粒度大,發(fā)生鎖沖突的概率高,并發(fā)處理能力低

注意:
InnoDB 支持表鎖和行鎖,使用索引作為檢索條件修改數(shù)據(jù)時采用行鎖,否則采用表鎖。

2.4 鎖的實現(xiàn)方式 (默認PR隔離級別)

innodb行鎖是給索引項加鎖實現(xiàn)的,所以如果沒有索引,會通過隱藏的聚簇索引來加鎖,和表鎖效果相同。

2.4.1 鎖的算法

[圖片上傳失敗...(image-a75577-1555250715381)]
[圖片上傳失敗...(image-f235aa-1555250715381)]

2.4.2 MVCC

MVCC (Multiversion Concurrency Control),即多版本并發(fā)控制技術(shù),它使得大部分支持行鎖的事務引擎,不再單純的使用行鎖來進行數(shù)據(jù)庫的并發(fā)控制,取而代之的是把數(shù)據(jù)庫的行鎖與行的多個版本結(jié)合起來,只需要很小的開銷,就可以實現(xiàn)非鎖定讀,從而大大提高數(shù)據(jù)庫系統(tǒng)的并發(fā)性能

MVCC只在 READ COMMITTED 和 REPEATABLE READ 兩個隔離級別下工作;
MVCC可以使用 樂觀(optimistic)鎖 和 悲觀(pessimistic)鎖來實現(xiàn);
相關(guān)文章

https://segmentfault.com/a/1190000012650596

2.5 快照讀和當前讀

當前讀:即加鎖讀,讀取記錄的最新版本,會加鎖保證其他并發(fā)事務不能修改當前記錄,直至獲取鎖的事務釋放鎖

快照讀:即不加鎖讀,讀取記錄的快照版本而非最新版本,通過MVCC實現(xiàn);
InnoDB默認的RR事務隔離級別下,不顯式加『lock in share mode』與『for update』的『select』操作都屬于快照讀,保證事務執(zhí)行過程中只有第一次讀之前提交的修改和自己的修改可見,其他的均不可見;

3.索引

http://www.cnblogs.com/itdragon/p/8146439.html
https://juejin.im/post/5b55b842f265da0f9e589e79
https://juejin.im/post/5b9fad345188255ca1537022
https://www.cnblogs.com/wade-luffy/p/6292784.html
https://fangjian0423.github.io/2017/07/05/mysql-index-summary/
https://blog.csdn.net/u010648555/article/details/81102957
https://segmentfault.com/a/1190000015416513
https://www.cnblogs.com/duanxz/p/5244703.html

3.1 索引的優(yōu)缺點

優(yōu)點:索引可以加快數(shù)據(jù)庫的檢索速度
缺點:索引會降低插入、刪除、修改等維護任務的速度。索引需要占物理和數(shù)據(jù)空間。

3.2 索引的原理

其實就是將無序的數(shù)據(jù)變成有序(相對):
[圖片上傳失敗...(image-5f2ff0-1555250715381)]

要找到id為8的記錄簡要步驟:
[圖片上傳失敗...(image-c6b9d8-1555250715381)]

3.3 索引的分類

3.3.1 普通索引

普通索引(單列索引):單列索引是最基本的索引,它沒有任何限制。

3.3.2 復合索引

復合索引:復合索引是在多個字段上創(chuàng)建的索引。復合索引遵守“最左前綴”原則,即在查詢條件中使用了復合索引的第一個字段,索引才會被使用。因此,在復合索引中索引列的順序至關(guān)重要。

3.3.3 唯一索引

唯一索引:唯一索引和普通索引類似,主要的區(qū)別在于,唯一索引限制列的值必須唯一,但允許存在空值(只允許存在一條空值)。

3.3.4 主鍵索引

主鍵索引是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。一般是在建表的時候同時創(chuàng)建主鍵索引:

3.3.5 全文索引

全文索引主要用來查找文本中的關(guān)鍵字,而不是直接與索引中的值相比較。fulltext索引跟其它索引大不相同,它更像是一個搜索引擎,而不是簡單的where語句的參數(shù)匹配。fulltext索引配合match against操作使用,而不是一般的where語句加like。目前只有char、varchar,text 列上可以創(chuàng)建全文索引。

3.4 聚集索引和輔助索引

聚集索引
聚集索引就是以主鍵創(chuàng)建的索引
一張表只粗在一個聚集索引
當一張表存在主鍵時就以主鍵構(gòu)造一顆B+樹創(chuàng)建聚集索引(innodb 必須存在)

輔助索引(非聚集索引,二級索引)
非聚集索引就是以非主鍵創(chuàng)建的索引
一張表可以有多個非聚集索引.
非聚集索引在葉子節(jié)點存儲的是主鍵和索引列,使用非聚集索引查詢出數(shù)據(jù)時,拿到葉子上的主鍵再去查到想要查找的數(shù)據(jù)。(拿到主鍵再查找這個過程叫做回表)
覆蓋索引就是把要查詢出的列和索引是對應的,不做回表操作!如下

//創(chuàng)建索引(username,age)
select username , age from user where username = 'Java3y' and age = 20
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容