數(shù)據(jù)庫事務(wù)
程序執(zhí)行單元筛武。
作用
- 提供數(shù)據(jù)庫操作從異常中恢復(fù)到正常狀態(tài)的方法佛吓,保證異常情況下數(shù)據(jù)一致性
- 多個應(yīng)用或者多個線程訪問數(shù)據(jù)庫隔離枢纠。
特點
- ACID
數(shù)據(jù)庫鎖
并發(fā)下保證穩(wěn)定性數(shù)據(jù)一致性。引擎有關(guān)巡通。
數(shù)據(jù)一致性問題:
- 臟讀
- 不可重復(fù)讀
- 幻讀
對應(yīng)解決:
事務(wù)隔離機制拦盹。
- 讀未提交
- 讀提交
- 可重復(fù)讀
- 串行化
表級別鎖(myISM)
意向鎖(Intention Locks)
意向鎖是一種表級鎖鹃祖,用來指示接下來的一個事務(wù)將要獲取的是什么類型的鎖(共享還是獨占)
行級別鎖(InnoDB)
mysql默認(rèn)innoDB溪椎。支持事務(wù)普舆,支持行級別鎖恬口。
共享鎖(s)
SELECT * FROM category WHERE category_no = 2 lock in SHARE mode; //共享鎖
獨占鎖(x)
SELECT * FROM category WHERE category_no = 2 for UPDATE; //獨占鎖
UPDATE category set category_name = '動漫' WHERE category_no = 2; //獨占鎖
記錄鎖(record Locks)
間隙鎖
隙鎖是一種記錄行與記錄行之間存在空隙或在第一行記錄之前或最后一行記錄之后產(chǎn)生的鎖。間隙鎖可能占據(jù)的單行沼侣,多行或者是空記錄祖能。
MYSQL鎖
- MySQL會對不存在的記錄加gap鎖,加gap鎖的目的是防止幻讀蛾洛。同時在事務(wù)1對某條不存在的記錄加鎖的過程中养铸,禁止插入其他新記錄,所以MySql中對不存的記錄加鎖相當(dāng)于此表不能插入任何記錄轧膘,非常危險钞螟,在實際的業(yè)務(wù)中一定要注意。
- 對于普通索引加鎖谎碍,事務(wù)會對數(shù)據(jù)加next-key鎖(即記錄鎖加上gap鎖)鳞滨,因為考慮到B+樹索引的有序性,滿足條件的項一定是連續(xù)存放的蟆淀,加gap鎖防止幻讀拯啦,必須要保證一事務(wù)內(nèi)連續(xù)兩次讀出都是一樣,所以上面的插入必定失敗熔任,不在范圍的數(shù)據(jù)插入才會成功
- 對唯一索引的記進(jìn)行讀取褒链,其他事務(wù)可以向表插入新的記錄,不能更新已加鎖的記錄疑苔,可以更新其他未加鎖的記錄甫匹,說明此時對表中已存在的記錄只加排他鎖。
- 對主鍵加鎖讀只會對該記錄加排他鎖夯巷,不會影響其他事務(wù)對記錄的插入和更新赛惩。
- 無索引條件下加鎖讀數(shù)據(jù)時,會導(dǎo)致全表加上索引趁餐,其他事務(wù)全部阻塞喷兼,數(shù)據(jù)庫基本會處于不可用狀態(tài)。
索引
作用
加快查詢
原理
- 為什么樹不是hash
加速查找速度的數(shù)據(jù)結(jié)構(gòu)后雷,常見的有兩類:
(1)哈希季惯,例如HashMap,查詢/插入/修改/刪除的平均時間復(fù)雜度都是O(1)臀突;
(2)樹勉抓,例如平衡二叉搜索樹,查詢/插入/修改/刪除的平均時間復(fù)雜度都是O(lg(n))候学;
select * from t where name=”sh”;
確實是哈希索引更快藕筋,因為每次都只查詢一條記錄。但是排序查詢的SQL需求:分組:group by梳码。排序:order by隐圾。比較:<伍掀、>。哈希型的索引暇藏,時間復(fù)雜度會退化為O(n)蜜笤,而樹型的“有序”特性,依然能夠保持O(log(n)) 的高效盐碱。 - 為什么是B+
二叉樹
image.png - 當(dāng)數(shù)據(jù)量大的時候把兔,樹的高度會比較高,數(shù)據(jù)量大的時候瓮顽,查詢會比較慢县好;
- 每個節(jié)點只存儲一個記錄,可能導(dǎo)致一次查詢有很多次磁盤IO
B樹
image.png - 不再是二叉搜索暖混,而是m叉搜索聘惦;
- 葉子節(jié)點,非葉子節(jié)點儒恋,都存儲數(shù)據(jù)善绎;
- 中序遍歷,可以獲得所有節(jié)點诫尽;
B樹被作為實現(xiàn)索引的數(shù)據(jù)結(jié)構(gòu)被創(chuàng)造出來禀酱,是因為它能夠完美的利用“局部性原理”。
局部性原理的邏輯是這樣的:
(1)內(nèi)存讀寫塊牧嫉,磁盤讀寫慢剂跟,而且慢很多;
(2)磁盤預(yù)讀:磁盤讀寫并不是按需讀取酣藻,而是按頁預(yù)讀曹洽,一次會讀一頁的數(shù)據(jù),每次加載更多的數(shù)據(jù)辽剧,如果未來要讀取的數(shù)據(jù)就在這一頁(4k)中送淆,可以避免未來的磁盤IO,提高效率怕轿;
(3)局部性原理:軟件設(shè)計要盡量遵循“數(shù)據(jù)讀取集中”與“使用到一個數(shù)據(jù)偷崩,大概率會使用其附近的數(shù)據(jù)”,這樣磁盤預(yù)讀能充分提高磁盤IO撞羽;
為啥用B樹
(1)由于是m分叉的阐斜,高度能夠大大降低;
(2)每個節(jié)點可以存儲j個記錄诀紊,如果將節(jié)點大小設(shè)置為頁大小谒出,例如4K,能夠充分的利用預(yù)讀的特性,極大減少磁盤IO笤喳;
b+樹
image.png
(1)范圍查找考赛,定位min與max之后,中間葉子節(jié)點莉测,就是結(jié)果集,不用中序回溯
(2)葉子節(jié)點存儲實際記錄行唧喉,記錄行相對比較緊密的存儲捣卤,適合大數(shù)據(jù)量磁盤存儲;非葉子節(jié)點存儲記錄的PK八孝,用于查詢加速董朝,適合內(nèi)存存儲;
(3)非葉子節(jié)點干跛,不存儲實際記錄子姜,而只存儲記錄的KEY的話,那么在相同內(nèi)存的情況下楼入,B+樹能夠存儲更多索引哥捕;
總結(jié) - 數(shù)據(jù)庫索引用于加速查詢
- 雖然哈希索引是O(1),樹索引是O(log(n))嘉熊,但SQL有很多“有序”需求遥赚,故數(shù)據(jù)庫使用樹型索引
- InnoDB不支持哈希索引
- 數(shù)據(jù)預(yù)讀的思路是:磁盤讀寫并不是按需讀取,而是按頁預(yù)讀阐肤,一次會讀一頁的數(shù)據(jù)凫佛,每次加載更多的數(shù)據(jù),以便未來減少磁盤IO
- 局部性原理:軟件設(shè)計要盡量遵循“數(shù)據(jù)讀取集中”與“使用到一個數(shù)據(jù)孕惜,大概率會使用其附近的數(shù)據(jù)”愧薛,這樣磁盤預(yù)讀能充分提高磁盤IO
數(shù)據(jù)庫的索引最常用B+樹:
(1)很適合磁盤存儲,能夠充分利用局部性原理衫画,磁盤預(yù)讀毫炉;
(2)很低的樹高度,能夠存儲大量數(shù)據(jù)削罩;
(3)索引本身占用的內(nèi)存很械夤俊;
(4)能夠很好的支持單點查詢鲸郊,范圍查詢丰榴,有序性查詢;