Mysql-InnoDB

  • B+樹
    B+樹是InnoDB底層采用的數(shù)據(jù)結(jié)構(gòu),它是一種多叉平衡搜索樹。InnoDB底層采用的存儲結(jié)構(gòu)就是B+樹窟却。
    它的優(yōu)點:

    1. 高度比較低遇汞,減少IO的次數(shù)
      因為B+樹采用是多叉樹未妹,所以在節(jié)點相同的情況下,比正常的二叉樹的高度低了很多空入。
      對于數(shù)據(jù)庫來說络它,最耗時的操作就是從磁盤加載數(shù)據(jù),因此想要提高數(shù)據(jù)庫的效率歪赢,必須盡量減少從磁盤加載數(shù)據(jù)的次數(shù)化戳。而對于多叉樹,父子節(jié)點往往相距比較遠埋凯,因此在數(shù)據(jù)量比較大的時候点楼,一次加載到父子節(jié)點幾乎是不可能的,最好的情況就是一次加載一個節(jié)點的數(shù)據(jù)白对,然后找到下一個節(jié)點進行加載掠廓,直到最后找到對應(yīng)的信息。
      從磁盤加載信息的時候甩恼,最耗時的操作是尋道蟀瞧,而從磁盤讀取數(shù)據(jù)到數(shù)據(jù)總線的耗時幾乎可以忽略,所以磁盤讀取數(shù)據(jù)的時候會有一個預(yù)讀的過程条摸。也就是說悦污,盡管你只要磁盤某個地方的一小段信息,加載的時候也會讀取滿一整個頁的信息钉蒲。所以切端,一個節(jié)點的大小設(shè)置成一個頁大小是最合適的,一次io可以加載進一個節(jié)點的所有信息顷啼,然后再決定下一個節(jié)點帆赢。


      B+樹
    2. 葉子節(jié)點有兄弟指針,方便遍歷
      有些情況下线梗,會出現(xiàn)需要全表掃描椰于,因為B+樹的所有信息都存在葉子節(jié)點,所以只要找到第一個葉子節(jié)點仪搔,然后依次根據(jù)兄弟節(jié)點指針找到兄弟節(jié)點瘾婿,最后就完成了整個數(shù)據(jù)庫的遍歷。
      而B樹等需要前序遍歷這種操作,在內(nèi)存中倒是沒有差別偏陪,但是如果是在磁盤中抢呆,因為父子節(jié)點往往不在一個頁中,遍歷就涉及到非常多的磁盤IO笛谦,效率很低抱虐。

  • 索引
    InnoDB使用的是聚簇索引表,即一棵以主鍵為索引饥脑、行數(shù)據(jù)存儲在子節(jié)點上的B+樹恳邀。如果沒有主鍵,系統(tǒng)先找一個not null 且unique的列作為主鍵灶轰,如果沒有谣沸,就會默認創(chuàng)建一個隱藏的主鍵作為索引。
    其他的索引都是一個獨立的結(jié)構(gòu)笋颤,利用這個結(jié)構(gòu)找到對應(yīng)的主鍵乳附,即通過其他索引找到數(shù)據(jù)需要先到對應(yīng)的索引樹找到主鍵伴澄,然后再到主鍵的索引樹上找到數(shù)據(jù)赋除。
    如果where條件中的鍵值沒有索引非凌,會掃描全表。


  • mysql中的鎖有很多種:

    1. 讀寫鎖
      讀寫鎖是最常見的兩種鎖清焕。讀鎖也叫共享鎖,允許其他人再獲得讀鎖祭犯,可以同時讀秸妥,但是不能更改數(shù)據(jù)沃粗。寫鎖也叫排他鎖,不允許其他人對數(shù)據(jù)進行讀或者寫最盅。
    2. Record Lock
      Record鎖是一種索引鎖突雪,它加在索引上防止被多次引用
    3. Gap Lock
      Gap鎖的出現(xiàn)主要是用來解決幻讀,鎖住一個區(qū)間涡贱,沒有拿到這個區(qū)間的Gap Lock咏删,就不能向這個區(qū)間插入问词。
    4. NextKey Lock
      NextKey鎖其實就是Record Lock和Gap Lock的組合體督函,同時鎖住一個范圍和其中的記錄
    5. 意向鎖
      意向所用來協(xié)調(diào)表鎖和行鎖。如果一個表有行排他鎖存在锋叨,那么想對表添加排他鎖,就一定要等這個行鎖釋放娃磺。但是想判斷表中是否存在行鎖只能遍歷叫倍,消耗太大偷卧。為了解決這個問題段标,產(chǎn)生了意向鎖。
      當(dāng)獲取一個行鎖時逼庞,會先拿到一個表的意向鎖,這樣只要判斷一個表是否有意向鎖赛糟,就可以判斷是否可以添加表鎖了。
  • 事務(wù)隔離級別

    1. read-uncommited
      在這個級別下掌逛,讀寫不會加任何鎖,所以即使事務(wù)沒有提交豆混,互相之間也能讀到彼此的更改动知。因此可能讀到對方更改一半的臟數(shù)據(jù)(臟讀)。
    2. read-commited(RC)
      在這個級別下盒粮,寫的時候會加寫鎖,即在一個事務(wù)在更改一個數(shù)據(jù)的時候丹皱,其他事務(wù)無法獲取這個數(shù)據(jù),直到這個事務(wù)釋放寫鎖之后摊崭。但是如果在那個事務(wù)更改之前讀了一次,更改之后又讀了一次汁讼,這兩次的結(jié)果會不一致(不可重復(fù)讀)。因此InnoDB采用了快照讀解決這個問題嘿架,即在每行數(shù)據(jù)添加一個隱藏字段,最新更改的事務(wù)id耸彪,如果當(dāng)前的事務(wù)id小于這個值, 就回去undo log中找到本事務(wù)對應(yīng)的值蝉娜,從而保證事務(wù)的一致性。
      但是如果其他事務(wù)插入了一條數(shù)據(jù)南缓,那么插入前這個事務(wù)是看不到那條數(shù)據(jù)的,但是插入之后汉形,這個事務(wù)就可以select到那個數(shù)據(jù)倍阐。也就是說概疆,同樣的select語句峰搪,前后兩次數(shù)據(jù)的會多或者少(幻讀)
    3. repeatable-read(RR)
      在這個級別下,為了解決幻讀使套,添加gap lock。即在select到的數(shù)據(jù)中間添加gap鎖侦高,其他想插入的事務(wù)必須要拿到這個gap鎖才能插入春锋,否則必須等待這個事務(wù)釋放gap鎖矫膨。
      4.SERIALIZABLE
      在RR的基礎(chǔ)上期奔,轉(zhuǎn)換所有 SELECT 語句為SELECT ... LOCK IN SHARE MODE危尿。即所有的讀和寫都要加鎖。
  • 死鎖
    造成死鎖的原因都是因為加鎖的順序不同谊娇,具體原因可以分為業(yè)務(wù)和索引。

    • 業(yè)務(wù)導(dǎo)致的死鎖


      業(yè)務(wù)層加鎖時順序不同

      這種情況比較常見赠堵,也比較容易解決小渊,在代碼中茫叭,兩個線程在加鎖的時候,加鎖順序不同揍愁,導(dǎo)致他們互相需要對方的鎖。

    • 索引導(dǎo)致的死鎖


      索引順序不同導(dǎo)致死鎖

      這種情況就比較特殊谬擦,我們在業(yè)務(wù)層幾乎感覺不到這種死鎖朽缎,因為這個涉及到mysql對索引的操作。兩個語句同時需要加鎖饵沧,而且條件是在兩個不同的索引。這樣加鎖順序就取決于主鍵在兩個索引的順序了狼牺。如圖中所示,兩個索引的順序相反是钥,加鎖的順序也就相反,容易死鎖虏冻。
      我們需要注意的就是,如果操作一個有多個索引的數(shù)據(jù)表厨相,盡量不要在多個索引上同時操作鸥鹉。

  • 分析方法

    • show engine innodb status

總結(jié)

  • InnoDB是通過索引實現(xiàn)的行鎖
    所以如果select中條件是一個沒有索引的列,那么會導(dǎo)致表鎖毁渗,如果事務(wù)隔離級別是RR,那么事務(wù)結(jié)束之前都不會釋放灸异。
  • 使用Gap鎖
    如果select一個不存在的數(shù)據(jù)羔飞,那么也會在對應(yīng)的區(qū)間添加gap鎖檐春。
    等于號的使用會影響范圍,不好的話會鎖住gap(next key)
  • 不使用索引
    1. 如果MySQL估計使用索引比全表掃描更慢疟暖,則不使用索引。例如誓篱,如果列key均勻分布在1和100之間,下面的查詢使用索引就不是很好:select * from table_name where key>1 and key<90;
    2. 如果使用MEMORY/HEAP表锦募,并且where條件中不使用“=”進行索引列邻遏,那么不會用到索引糠亩,head表只有在“=”的條件下才會使用索引
    3. 用or分隔開的條件准验,如果or前的條件中的列有索引,而后面的列沒有索引糊饱,那么涉及到的索引都不會被用到,例如:select * from table_name where key1='a' or key2='b';如果在key1上有索引而在key2上沒有索引滞项,則該查詢也不會走索引
    4. 復(fù)合索引夭坪,如果索引列不是復(fù)合索引的第一部分文判,則不使用索引(即不符合最左前綴)室梅,例如,復(fù)合索引為(key1,key2),則查詢select * from table_name where key2='b';將不會使用索引
    5. 如果like是以‘%’開始的亡鼠,則該列上的索引不會被使用。例如select * from table_name where key1 like '%a'嗓奢;該查詢即使key1上存在索引浑厚,也不會被使用
    6. 如果列為字符串股耽,則where條件中必須將字符常量值加引號钳幅,否則即使該列上存在索引扮授,也不會被使用。例如,select * from table_name where key1=1;如果key1列保存的是字符串钠导,即使key1上有索引,也不會被使用牡属。
  • 重復(fù)加鎖
    對不存在的記錄加排他鎖,都會加鎖成功逮栅。即gap鎖的x鎖不互斥。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末特纤,一起剝皮案震驚了整個濱河市侥加,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌担败,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件傻咖,死亡現(xiàn)場離奇詭異岖研,居然都是意外死亡卿操,警方通過查閱死者的電腦和手機孙援,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來窥摄,“玉大人础淤,你說我怎么就攤上這事哨苛。” “怎么了建峭?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵决摧,是天一觀的道長。 經(jīng)常有香客問我掌桩,道長,這世上最難降的妖魔是什么砚蓬? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任盆色,我火速辦了婚禮,結(jié)果婚禮上隔躲,老公的妹妹穿的比我還像新娘。我一直安慰自己宣旱,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布笙纤。 她就那樣靜靜地躺著组力,像睡著了一般。 火紅的嫁衣襯著肌膚如雪燎字。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天笼蛛,我揣著相機與錄音,去河邊找鬼滨砍。 笑死,一個胖子當(dāng)著我的面吹牛惋戏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播日川,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼龄句,長吁一口氣:“原來是場噩夢啊……” “哼散罕!你這毒婦竟也來了分歇?” 一聲冷哼從身側(cè)響起欧漱,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎缚甩,沒想到半個月后窑邦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體擅威,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡郊丛,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年瞧筛,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片较幌。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖月培,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杉畜,我是刑警寧澤衷恭,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站随珠,受9級特大地震影響猬错,放射性物質(zhì)發(fā)生泄漏茸歧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一软瞎、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧鳖藕,春花似錦、人聲如沸著恩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纵顾。三九已至,卻和暖如春片挂,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背音念。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工闷愤, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留整葡,地道東北人讥脐。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像俱萍,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子枪蘑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容