[toc]
1.事務
1.1 隔離級別和特性
事務的特性ACID
- A Atomicity 原子性 執行的完整性,不可拆分
- C Consistency 一致性 數據庫一致性保持不變
- I Isolation 隔離性 隔離性確保事務并發執行后的系統狀態與這些事務以某種次序串行執行以后的狀態是等價的。
- D Durability 持久性 執行后結果存儲
事務隔離級別
可串行化(Serializable):sql中最高的隔離性級別,能夠避免臟讀,幻讀,不可重復讀。代價也相對沉重,會大大影響數據庫的性能。可重復讀(Repeatable read):只允許讀取已提交的數據,而且在一個事務兩次讀取一個數據項期間,其他事務不得更新該數據。這種狀態不能避免幻讀。
已提交讀(Read committed):只允許讀取已提交數據,但不要求可重復讀。這種狀態只能避免臟讀。
未提交讀(Read uncommitted):允許讀取未提交的數據。這是最低的隔離級別,臟讀,幻讀,不可重復讀都無法避免。
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通常是物理日志,記錄的是數據頁的物理修改,而不是某一行或某幾行修改成怎樣怎樣,它用來恢復提交后的物理數據頁(恢復數據頁,且只能恢復到最后一次提交的位置。
2.undo用來回滾行記錄到某個版本。undo log一般是邏輯日志,根據每行記錄進行記錄
事務日志可以幫助提高事務的效率。保證事務的持久性。
寫日志采用追加方式。
數據庫重啟和奔潰時可以從redolog慢慢刷會磁盤。
事務恢復策略
A. 進行恢復時,只重做已經提交了的事務。
B. 進行恢復時,重做所有事務包括未提交的事務和回滾了的事務。然后通過Undo Log回滾那些
未提交的事務。 innodb 采用
1.3 事務的相關操作
1.查看當前會話隔離級別
select @@tx_isolation;
2.查看系統當前隔離級別
select @@global.tx_isolation;
3.設置當前會話隔離級別
set session transaction isolatin level repeatable read;
4.設置系統當前隔離級別
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
2.1 鎖的類型
2.1.1 共享鎖S
允許一個事務去讀一行,阻止其他事務獲得相同的數據集的排他鎖。
select ... in share mode
共享鎖就是我讀的時候,你可以讀,但是不能寫。
2.1.2 排他鎖X
允許獲得排他鎖的事務更新數據,但是組織其他事務獲得相同數據集的共享鎖和排他鎖。
select ... for update
排他鎖就是我寫的時候,你不能讀也不能寫。。
2.1.3 意向共享鎖IS
表示事務準備給數據行加入共享鎖,也就是說一個數據行加共享鎖前必須先取得該表的IS鎖
2.1.4 意向排他鎖 IX
表示事務準備給數據行加入排他鎖,說明事務在一個數據行加排他鎖前必須先取得該表的IX鎖。
2.1.5 鎖的兼容+ 意向鎖的意義
當一個事務請求的鎖模式與當前的鎖兼容,InnoDB就將請求的鎖授予該事務;反之如果請求不兼容,則該事務就等待鎖釋放。
意向鎖是為了實現多粒度鎖,是數據庫自動加持的。
對于意向鎖的理解
意向鎖是一種快速判斷表鎖與之前可能存在的行鎖沖突的機制
事務A鎖住了表中的一行,讓這一行只能讀,不能寫。之后,事務B申請整個表的寫鎖。如果事務B申請成功,那么理論上它就能修改表中的任意一行,這與A持有的行鎖是沖突的。數據庫需要避免這種沖突,就是說要讓B的申請被阻塞,直到A釋放了行鎖。數據庫要怎么判斷這個沖突呢?step1:判斷表是否已被其他事務用表鎖鎖表step2:判斷表中的每一行是否已被行鎖鎖住。注意step2,這樣的判斷方法效率實在不高,因為需要遍歷整個表。于是就有了意向鎖。在意向鎖存在的情況下,事務A必須先申請表的意向共享鎖,成功后再申請一行的行鎖。在意向鎖存在的情況下,上面的判斷可以改成step1:不變step2:發現表上有意向共享鎖,說明表中有些行被共享行鎖鎖住了,因此,事務B申請表的寫鎖會被阻塞。
。
2.2 加鎖機制和思想
2.2.1 樂觀鎖
樂觀鎖會“樂觀地”假定大概率不會發生并發更新沖突,訪問、處理數據過程中不加鎖,只在更新數據時再根據版本號或時間戳判斷是否有沖突,有則處理,無則提交事務
實踐 偽代碼
select version from xxxxx
......
update xxxxx set version=version+1 where version=#{version}
//更新的時候確保version是之錢讀取的version
2.2.2 悲觀鎖
悲觀鎖會“悲觀地”假定大概率會發生并發更新沖突,訪問、處理數據前就加排他鎖,在整個數據處理過程中鎖定數據,事務提交或回滾后才釋放鎖;
實踐
select xxx from xxx for update //直接獲取排他鎖
2.3 鎖的粒度
2.3.1 行鎖
行鎖的解釋: 對記錄的鎖
行鎖的劣勢:開銷大;加鎖慢;會出現死鎖
行鎖的優勢:鎖的粒度小,發生鎖沖突的概率低;處理并發的能力強
2.3.2 表鎖
表鎖的解釋: 對表的鎖
表鎖的優勢:開銷小;加鎖快;無死鎖
表鎖的劣勢:鎖粒度大,發生鎖沖突的概率高,并發處理能力低
注意:
InnoDB 支持表鎖和行鎖,使用索引作為檢索條件修改數據時采用行鎖,否則采用表鎖。
2.4 鎖的實現方式 (默認PR隔離級別)
innodb行鎖是給索引項加鎖實現的,所以如果沒有索引,會通過隱藏的聚簇索引來加鎖,和表鎖效果相同。
2.4.1 鎖的算法
[圖片上傳失敗...(image-a75577-1555250715381)]
[圖片上傳失敗...(image-f235aa-1555250715381)]
2.4.2 MVCC
MVCC (Multiversion Concurrency Control),即多版本并發控制技術,它使得大部分支持行鎖的事務引擎,不再單純的使用行鎖來進行數據庫的并發控制,取而代之的是把數據庫的行鎖與行的多個版本結合起來,只需要很小的開銷,就可以實現非鎖定讀,從而大大提高數據庫系統的并發性能
MVCC只在 READ COMMITTED 和 REPEATABLE READ 兩個隔離級別下工作;
MVCC可以使用 樂觀(optimistic)鎖 和 悲觀(pessimistic)鎖來實現;
相關文章
2.5 快照讀和當前讀
當前讀:即加鎖讀,讀取記錄的最新版本,會加鎖保證其他并發事務不能修改當前記錄,直至獲取鎖的事務釋放鎖
快照讀:即不加鎖讀,讀取記錄的快照版本而非最新版本,通過MVCC實現;
InnoDB默認的RR事務隔離級別下,不顯式加『lock in share mode』與『for update』的『select』操作都屬于快照讀,保證事務執行過程中只有第一次讀之前提交的修改和自己的修改可見,其他的均不可見;
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 索引的優缺點
優點:索引可以加快數據庫的檢索速度
缺點:索引會降低插入、刪除、修改等維護任務的速度。索引需要占物理和數據空間。
3.2 索引的原理
其實就是將無序的數據變成有序(相對):
[圖片上傳失敗...(image-5f2ff0-1555250715381)]
要找到id為8的記錄簡要步驟:
[圖片上傳失敗...(image-c6b9d8-1555250715381)]
3.3 索引的分類
3.3.1 普通索引
普通索引(單列索引):單列索引是最基本的索引,它沒有任何限制。
3.3.2 復合索引
復合索引:復合索引是在多個字段上創建的索引。復合索引遵守“最左前綴”原則,即在查詢條件中使用了復合索引的第一個字段,索引才會被使用。因此,在復合索引中索引列的順序至關重要。
3.3.3 唯一索引
唯一索引:唯一索引和普通索引類似,主要的區別在于,唯一索引限制列的值必須唯一,但允許存在空值(只允許存在一條空值)。
3.3.4 主鍵索引
主鍵索引是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。一般是在建表的時候同時創建主鍵索引:
3.3.5 全文索引
全文索引主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較。fulltext索引跟其它索引大不相同,它更像是一個搜索引擎,而不是簡單的where語句的參數匹配。fulltext索引配合match against操作使用,而不是一般的where語句加like。目前只有char、varchar,text 列上可以創建全文索引。
3.4 聚集索引和輔助索引
聚集索引
聚集索引就是以主鍵創建的索引
一張表只粗在一個聚集索引
當一張表存在主鍵時就以主鍵構造一顆B+樹創建聚集索引(innodb 必須存在)
輔助索引(非聚集索引,二級索引)
非聚集索引就是以非主鍵創建的索引
一張表可以有多個非聚集索引.
非聚集索引在葉子節點存儲的是主鍵和索引列,使用非聚集索引查詢出數據時,拿到葉子上的主鍵再去查到想要查找的數據。(拿到主鍵再查找這個過程叫做回表)
覆蓋索引就是把要查詢出的列和索引是對應的,不做回表操作!如下
//創建索引(username,age)
select username , age from user where username = 'Java3y' and age = 20