国产精品电影_久久视频免费_欧美日韩国产激情_成年人视频免费在线播放_日本久久亚洲电影_久久都是精品_66av99_九色精品美女在线_蜜臀a∨国产成人精品_冲田杏梨av在线_欧美精品在线一区二区三区_麻豆mv在线看

明明在InnoDB執(zhí)行了delete,為啥數(shù)據(jù)刪了個寂寞?

數(shù)據(jù)庫 其他數(shù)據(jù)庫
我們知道InnoDB存儲引擎是支持MVCC的,即多版本控制,得益于MVCC,MySQL在事務(wù)里查詢數(shù)據(jù)的時候不需要加鎖,可以提供很好的并發(fā)性,同時提供可重復(fù)讀這個很重要的特性。那么它是怎么到的呢?

一、刪除并不是真正的刪除

熟悉MySQL InnoDB存儲引擎的同學(xué)都應(yīng)該知道,當(dāng)我們執(zhí)行delete的時候,數(shù)據(jù)并沒有被真正的刪除,只是對應(yīng)數(shù)據(jù)的刪除標(biāo)識deleteMark被打開了,這樣每次執(zhí)行查詢的時候,如果發(fā)現(xiàn)數(shù)據(jù)存在但是deleteMark是開啟的話,那么依然返回空,因?yàn)檫@個細(xì)節(jié),所以經(jīng)常會出現(xiàn)“我明明刪除了數(shù)據(jù),為什么空間沒釋放”的現(xiàn)象。

15M  7  6 18:46 user_info.ibd #刪除前
15M 10 4 16:47 user_info.ibd #刪除后

二、為什么不直接刪除,而是打個標(biāo)記

我們知道InnoDB存儲引擎是支持MVCC的,即多版本控制,得益于MVCC,MySQL在事務(wù)里查詢數(shù)據(jù)的時候不需要加鎖,可以提供很好的并發(fā)性,同時提供可重復(fù)讀這個很重要的特性。那么它是怎么到的呢?答案是undo log,可以簡單的理解為,每次更新數(shù)據(jù)的時候?qū)⒏虑暗臄?shù)據(jù)先寫入undo log中,這樣當(dāng)需要回滾的時候,只需要順著undo log找到歷史數(shù)據(jù)即可。undo log與原始數(shù)據(jù)之間是用指針鏈接起來的,即每條數(shù)據(jù)都有個回滾指針指向undo log。

如果InnoDB在刪除數(shù)據(jù)的時候,真的是把數(shù)據(jù)從磁盤上擦除,那么這時候:

  • 別的事務(wù)通過undo log是無法找到原始數(shù)據(jù)。
  • 可重復(fù)讀這個特性會被破壞。

三、只是打個標(biāo)記的話,豈不是很浪費(fèi)空間

MySQL里面有個purge線程,它的工作中有一項(xiàng)任務(wù)就是專門檢查這些有deleteMark的數(shù)據(jù),當(dāng)有deleteMark的數(shù)據(jù)如果沒有被其他事務(wù)引用時,那么會被標(biāo)記成可復(fù)用,因?yàn)槿~子節(jié)點(diǎn)數(shù)據(jù)是有序的原因,這樣當(dāng)下次有同樣位置的數(shù)據(jù)插入時,可以直接復(fù)用這塊磁盤空間。當(dāng)整個頁都可以復(fù)用的時候,也不會把它還回去,會把可復(fù)用的頁留下來,當(dāng)下次需要新頁時可以直接使用,從而減少頻繁的頁申請。

四、基于頁的存儲方式

我們知道MySQL數(shù)據(jù)是存儲在磁盤上的,磁盤的速度想必大家都知道,特別是當(dāng)發(fā)生隨機(jī)IO的時候。這里簡單解釋下什么叫IO,以機(jī)械磁盤為例,我們最終的數(shù)據(jù)都是落在磁盤的一個一個扇區(qū)上的,當(dāng)一個扇區(qū)寫滿了,就得換下一個扇區(qū),這時就要通過盤片的轉(zhuǎn)動找到目標(biāo)扇區(qū),這是物理運(yùn)動。如果要寫入的下一個扇區(qū)和當(dāng)前的扇區(qū)是緊挨著的,這叫順序IO,如果要寫入的扇區(qū)和當(dāng)前的扇區(qū)中間隔了幾個扇區(qū),這叫隨機(jī)IO,很明顯隨機(jī)IO需要更長的轉(zhuǎn)動時間。所以查詢一個數(shù)據(jù)的時候,減少IO是非常關(guān)鍵的,特別是隨機(jī)IO。

為了減少磁盤IO,MySQL采用B+樹的索引結(jié)構(gòu)來組織數(shù)據(jù),B+樹的特點(diǎn)是矮胖,一般樹的高度就代表了IO的次數(shù),越矮的話,樹的高度越低,那么對應(yīng)的IO次數(shù)就越少,還有一點(diǎn)需要知道的是數(shù)據(jù)最終都在葉子節(jié)點(diǎn)上,所以在B+樹上搜索的時候,一定是要檢索到最后一層葉子節(jié)點(diǎn)上,這是一種穩(wěn)定性的表現(xiàn)。

1、行與頁

這里需要知道的是,我們最終通過B+樹檢索到的不是我們的目標(biāo)行數(shù)據(jù),而是目標(biāo)行數(shù)據(jù)所在的頁,這個頁上有很多數(shù)據(jù),都是索引序號相鄰的,當(dāng)找到目標(biāo)頁后,會把目標(biāo)頁加載到內(nèi)存中,然后通過二分法找到目標(biāo)數(shù)據(jù)。

也許你會問,那搜索的開銷不僅僅是磁盤IO,還有在二分法查找的開銷。這里不可否認(rèn),但是我們一般忽略這部分開銷,因?yàn)閏pu在內(nèi)存里檢索的速度很快,并且一頁也就16k,數(shù)據(jù)并不多。

2、IO次數(shù)不一定等于樹的高度

前面我們說到樹的高度等于IO的次數(shù),這其實(shí)不是很準(zhǔn)確,我們知道樹的根節(jié)點(diǎn)一定是在內(nèi)存里的,那么對于一顆高度為3的數(shù)據(jù),只用2次IO即可,這其實(shí)可以理解,畢竟根節(jié)點(diǎn)只占用一頁的空間,一頁才16K,放在內(nèi)存里綽綽有余。但有時候樹的第二層也可以放在內(nèi)存里。

假設(shè)現(xiàn)在主鍵是bigint,bigint我們知道占用8個字節(jié),對于一個索引來說除了類型本身占用空間之外,還有一個指針,這個指針占用6個字節(jié),那么對于根節(jié)點(diǎn)來說它大概能存 16K/(8+6)B = 1170 個數(shù)據(jù),每個數(shù)據(jù)都可以指向一頁(也就是它的下一層),這樣整個樹的第二層大概占用 1170*16K = 18M 的空間,這也不是一個很大的數(shù)字,對于機(jī)器的內(nèi)存來說,幾乎也是滄海一粟,所以第二層往往也在內(nèi)存里,所以最終在B+樹上檢索數(shù)據(jù)所消耗的IO應(yīng)該比理論的要低。

通過上面我們知道檢索一條數(shù)據(jù)的快慢,主要受樹的高度影響的,這和你的數(shù)據(jù)表的大小并沒有太大的關(guān)系,現(xiàn)實(shí)中有人可能在數(shù)據(jù)表達(dá)到百萬級別的時就考慮分表,個人認(rèn)為這有點(diǎn)低估B+樹的能力了。還是以bigint類型的主鍵索引為例,假設(shè)一行數(shù)據(jù)占用1K(理論上已經(jīng)足夠大了),那么一頁可以存下 16K/1K=16 條數(shù)據(jù),對于一顆高度為3的B+樹來說,它可以存下 1170*1170*16=21902400 的數(shù)據(jù),將近2千萬,如果你的數(shù)據(jù)行占用的空間更小,就可以存下更多的數(shù)據(jù),所以只是簡單的根據(jù)數(shù)據(jù)行數(shù)來判斷是否需要分表不是那么的合理。

五、可復(fù)用的空間一直沒有被利用咋辦

前面我們說到刪除的數(shù)據(jù)不會被真的刪除,只是打上個deleteMark的標(biāo)識,然后會被復(fù)用,但是如果一直沒被復(fù)用,那么空間不就是白白的浪費(fèi)了,更糟糕的是,如果刪除的很多數(shù)據(jù)空間都沒有被復(fù)用,就會造成頁空間存在大量的碎片,為了解決這種情況,MySQL內(nèi)部有個叫頁合并的功能,這是什么意思呢?簡單理解就是頁A現(xiàn)在有很多可以被復(fù)用的空間,它的鄰居頁B也有很多可以復(fù)用的空間,此時頁A就可以和頁B合并,如果合并后能省出來一頁,那么多出來的一頁就可以被下次使用,從而達(dá)到頁最大利用的效果。

合并的關(guān)鍵需要當(dāng)前頁的前一頁或者后一頁也有大量的碎片空間,這里為何要「大量」很關(guān)鍵,合并的動作可以簡單理解就是把別的頁的數(shù)據(jù)移動過來,如果兩個頁pageA和pageB都只有少量的可復(fù)用空間,那么合并后,即使pageA可以填滿,但是另一個頁P(yáng)age也還是有碎片空間的,并且碎片更大,這時候數(shù)據(jù)移動的開銷可能要大于存儲的開銷,得不償失。

而且還會有個嚴(yán)重的問題,pageB可能會和pageC合并,那么pageC的碎片更大...,這樣的話似乎是個無底洞,導(dǎo)致很多頁都在移動數(shù)據(jù)。因此一個合理的合并條件很關(guān)鍵,InnoDB中何時合并受MERGE_THRESHOLD這個參數(shù)影響,它的默認(rèn)值是50%,50%的意圖很明顯,兩個50%就可以省出一個頁。

我們看個例子,pageA已經(jīng)有50%的數(shù)據(jù)被刪除了,它的鄰居pageB只使用了不到50%的數(shù)據(jù),這時候會將pageB的數(shù)據(jù)移動到pageA上,那么整個pageB就是空頁了,可以提供給別的數(shù)據(jù)使用。這里需要知道的是除了刪除會觸發(fā)頁合并外,更新可能也會觸發(fā)頁合并。

六、有合并也有分裂

合并頁是提升頁的利用率的方式,但是有時候我們又不得不分裂頁,我們知道葉子節(jié)點(diǎn)的頁之間是用雙向鏈表串接起來的,并且頁與頁之間的數(shù)據(jù)是有序的。

以上圖為例,當(dāng)我們要插入5這條數(shù)據(jù),按道理應(yīng)該嘗試放在pageA里面,但是pageA目前沒有足夠的空間來存放一條數(shù)據(jù),于是嘗試找到pageA的相鄰頁pageB,但是此時很不幸的是pageB也沒有足夠的空間來存放一條數(shù)據(jù),由于要求數(shù)據(jù)的連續(xù)性,數(shù)據(jù)5必須在數(shù)據(jù)4和數(shù)據(jù)6之間,那么只能新建一個頁,新建一個頁后,會嘗試從pageA中移動一部分?jǐn)?shù)據(jù)到新的頁上,并且會重新組織頁與頁之間的關(guān)系,即在pageA和pageB之間會隔一道新頁pageC。

頁分裂會造成頁的利用率降低,造成頁分裂的原因有很多,比如:

  • 比如離散的插入,導(dǎo)致數(shù)據(jù)不連續(xù)。
  • 把記錄更新成一個更大記錄,導(dǎo)致空間不夠用。

還有一點(diǎn)需要知道的是:不管是頁的合并還是頁的分裂,都是相對耗時的操作,除了移動數(shù)據(jù)的開銷外,InnoDB也會在索引樹上加鎖。

七、手動重建表

頁的合并和分裂主要是在插入、刪除或更新的時候,并且正好滿足某些條件才發(fā)生的,那如果這些條件一直不滿足,碎片就無法得到清理,這時候往往會出現(xiàn)"我的表明明沒多少數(shù)據(jù),為什么還占用這么大空間"這個現(xiàn)象,針對這個現(xiàn)象有人說重建索引,這個是對的,重建索引可以讓數(shù)據(jù)更加緊湊,頁的利用率達(dá)到更高。但是如何重建索引?第一時間你可能會想到先drop index然后add index,這個似乎不是那么準(zhǔn)確。

如果要重建的索引是普通索引,使用這種方式還好,需要注意的是假如你的業(yè)務(wù)TPS很大,建議在業(yè)務(wù)低峰期執(zhí)行,因?yàn)殡m然MySQL支持online ddl,但是重建索引的過程還是很耗cpu和io資源的。

如果你要重建的是主鍵索引,那么問題來了,首先如果你的主鍵索引設(shè)置的是自增長,是不支持drop的。其次如果你的主鍵沒設(shè)置成自增長,直接drop也不是我們想象的那樣,我們知道普通索引除了記錄本身的索引字段外,還會記錄主鍵的值,如果drop是直接刪除索引,那么通過普通引將找不到對應(yīng)的行記錄,所以InnoDB是要求必須有主鍵索引的,這時InnoDB會嘗試去表中找個唯一索引來當(dāng)主鍵,如果沒有唯一索引,那就自動創(chuàng)建一個默認(rèn)的主鍵索引rowid,當(dāng)新的主鍵索引建立好之后,還要去修改相關(guān)的普通索引讓其存儲新的主鍵,但是如果按照這種方法來修改的話,開銷會很大,特別是普通索引很多的情況下,于是InnoDB干脆選擇重建表。對于緊接著執(zhí)行的add index操作,同樣也會發(fā)生主鍵索引的變更,所以也會選擇重建表,最終可以發(fā)現(xiàn)在主鍵索引上的drop和add其實(shí)干了一樣的事情。

綜上所述,一般在你的表出現(xiàn)很多頁碎片的時候,建議使用:

alter table xx engine=InnoDB

這個命令可以重建我們這個表,但是前提是我們的表是獨(dú)占表空間的。基于MySQL的online ddl,這個過程它是不影響正常的讀寫的,它的過程如下:

  • 掃描原表主鍵索引的所有記錄
  • 生成新的b+樹記錄到臨時文件
  • 生成臨時文件的過程中,新的變更記錄到一個中轉(zhuǎn)日志row log中
  • 在臨時文件生成后,將期間row log的變更應(yīng)用到新的臨時文件中
  • 然后替換臨時文件為當(dāng)前文件

這里需要注意的是重建表的過程涉及到數(shù)據(jù)的copy,得保證磁盤有足夠的空間,至少是現(xiàn)在磁盤空間的1倍,如果磁盤空間不足,那么是不會重建成功的。

八、重建表不一定會收縮空間

在重建表的過程中,有一點(diǎn)需要知道:InnoDB不會讓重建后的頁充滿數(shù)據(jù),會預(yù)留個「1/16」的空間,這個意圖很明顯,如果不預(yù)留,選擇占滿整個頁,這時候去更新一條需要更大空間的老數(shù)據(jù),就會需要新的頁,寫入新的頁后,往往又會造成碎片,所以提前預(yù)留一點(diǎn)空間是有用的。

但是因?yàn)檫@個預(yù)留操作,某些情況下會導(dǎo)致重建后的表空間反而會變大。

  • 如果你的表本身就很緊湊,因?yàn)轭A(yù)留1/16會變大。
  • 在第一次重建表后,因?yàn)樾碌牟迦雽?dǎo)致用掉了預(yù)留空間的一部分(這里需要注意的是預(yù)留空間沒用完,還剩一部分),但是沒有用到新的頁,所以整體的空間沒有變化,這時候如果再次重建表,就會因?yàn)橐A(yù)留1/16,導(dǎo)致申請的新的頁,那么空間就會變大。
責(zé)任編輯:未麗燕 來源: 假裝懂編程
相關(guān)推薦

2021-04-08 09:49:49

MySQL索引數(shù)據(jù)庫

2020-07-21 09:05:47

CPU1號核寄存器

2021-08-26 16:55:26

耦合服務(wù)化架構(gòu)

2018-08-23 09:10:01

數(shù)據(jù)庫MySQLInnoDB

2018-08-27 07:29:34

InnoDBinsertselect

2022-05-08 13:17:14

CPU內(nèi)存中斷

2020-06-28 09:12:31

CPU網(wǎng)卡中斷

2022-03-07 10:54:34

內(nèi)存Linux

2021-12-20 08:41:14

年終獎老板公司

2021-08-31 06:51:18

Babel前端開發(fā)

2010-04-06 09:58:13

Oracle dele

2021-10-07 09:06:48

DeletesqlSELECT

2010-04-26 16:23:52

Oracle dele

2010-04-27 11:43:41

Oracle dele

2025-03-28 08:30:00

PythonPandasaxis

2020-01-15 15:29:52

InnoDB數(shù)據(jù)硬盤

2021-06-28 07:13:35

SQL語句索引

2021-09-02 11:37:28

微軟操作系統(tǒng)Windows

2025-06-12 03:25:00

2020-05-19 08:30:33

kill -9命令Linux
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

99在线观看免费视频精品观看| 欧美亚洲在线| 7777精品伊人久久久大香线蕉经典版下载 | 欧洲成人性视频| 色呦呦在线观看视频| 亚洲视频免费观看| 少妇高清精品毛片在线视频| 日产国产高清一区二区三区| 亚洲aaa激情| 国产一区二区在线| 1769国产精品| 加勒比色综合久久久久久久久| 国产亚洲精品美女久久久| а√在线天堂官网| 911精品国产一区二区在线| 九色视频网站在线观看| 亚洲h在线观看| 伊人色综合久久| 精品国产91久久久久久| 中文字幕国产在线| 精品日韩中文字幕| 日韩美女一级视频| 91小视频xxxx网站在线| 欧美重口另类| 中文字幕成人在线观看| 午夜在线a亚洲v天堂网2018| 性欧美大战久久久久久久久| 国产精品夜间视频香蕉| 黄色综合网址| 欧美精选一区二区| 日本免费一区二区三区| 亚洲最大在线| 免费看的黄色大片| 久久 天天综合| 台湾无码一区二区| 成人动漫一区二区在线| 黄色一级视频片| 国产精品传媒入口麻豆| 探花国产精品| 精品福利樱桃av导航| 国产裸舞福利在线视频合集| 欧美成人bangbros| 国产精品极品美女在线观看| 久久久av网站| 免费看日本一区二区| 99久久精品无码一区二区毛片 | 波多一区二区| 亚洲欧美国产视频| 国产91社区| 蜜臀国产一区| 久久日韩粉嫩一区二区三区| 成人欧美一区二区三区黑人免费| 亚洲香蕉伊在人在线观| 国产美女高潮在线| 国产一区二区三区在线视频| 成人性生交大片免费看96| 亚洲人成网站在线播| 91精品福利| 精品视频免费在线播放| 欧美成人精品三级网站| 国产精品人成在线观看免费 | 国产福利成人在线| 久久99国产精品麻豆| 日本中文字幕一区二区有码在线| 亚洲欧美日韩精品久久奇米色影视| 最近久乱中文字幕| 日韩一区二区三区免费看| 91精品啪在线观看国产爱臀 | 欧美日韩dvd在线观看| 日韩一区二区免费高清| 欧美成年人在线观看| 91久久久一线二线三线品牌| 免费网站黄在线观看| 警花av一区二区三区| 中文字幕最新精品| 3d动漫一区二区三区在线观看| 全亚洲最色的网站在线观看| 青青草国产成人a∨下载安卓| 91久久精品美女| 久久99热99| 久久人妻精品白浆国产| 欧美色倩网站大全免费| 在线中文字幕-区二区三区四区| 亚洲国产天堂网精品网站| 国产精品中文字幕制服诱惑| 国产精品视频26uuu| 精品国产一区探花在线观看| 中文字幕成人一区| 国产亚洲精品久| 成人欧美在线| 久久精品久久精品亚洲人| 日韩中文av| 亚洲国产精品久久久久婷婷老年| 99精品视频在线免费观看| 2019中文字幕在线视频| 色偷偷av一区二区三区| 91一区在线| 男女高潮又爽又黄又无遮挡| 欧美日韩激情美女| 综合伊人久久| 日本一区网站| 一区二区三区在线免费视频| 日韩制服一区| 亚洲综合成人婷婷小说| 中文字幕久久午夜不卡| 伊人免费在线| 久久av资源网站| 日韩国产成人精品| 国产精品入口免费软件| 亚洲精品国产精品自产a区红杏吧| 成人资源在线播放| 96精品久久久久中文字幕| 日本一区二区免费在线观看视频| 国产黄在线看| 国产精品视频99| 国产成人亚洲综合色影视| 性一爱一乱一交一视频| 国产一区二区三区久久精品| 88国产精品视频一区二区三区| 成人观看视频| 国产午夜精品麻豆| 一本久久综合| 嫩模私拍啪啪| 最近2019年日本中文免费字幕| 午夜精品视频| 成人网18免费看| 欧美激情视频网站| 日本视频中文字幕一区二区三区| 成年人在线看| 国产成人精品视频在线| 人妖欧美一区二区| av香蕉成人| 亚洲va久久久噜噜噜| 婷婷夜色潮精品综合在线| 中文字幕电影在线| 欧美一区三区三区高中清蜜桃| 日韩欧美有码在线| 成人情趣视频网站| 欧美性猛交内射兽交老熟妇| 欧美性开放视频| 日本高清在线观看视频| 成年无码av片在线| 爽好多水快深点欧美视频| 亚洲一区二区三区欧美| 色八戒一区二区三区| 同性恋视频一区| 蜜桃传媒视频第一区入口在线看| 亚洲精品国久久99热| 亚洲国产91| 日本一区二区成人| www中文字幕在线观看| 欧洲精品国产| 日本道色综合久久| 国产欧美日本| 中文字幕在线精品| 国产福利一区二区| 97久久香蕉国产线看观看| 亚洲国内在线| 日韩一区二区久久久| 99视频在线精品| 福利一区在线| 99久久国产综合精品五月天喷水| 亚洲国产精品电影| 国产精品一区二区三区99| 欧美美女喷水视频| 亚洲丁香婷深爱综合| 热久久免费视频精品| 看电视剧不卡顿的网站| 欧美精品日韩少妇| 特级西西444www大精品视频| 欧美人与z0zoxxxx视频| 日韩欧美精品在线| 中文字幕欧美一| 视频一区在线播放| 人人视频精品| 久久久精品麻豆| 2019日本中文字幕| 成人不卡免费av| 四虎影视精品永久在线观看| 欧美精品日本| 成人av影院在线观看| 制服丝袜综合日韩欧美| 久久在精品线影院精品国产| 91小视频在线观看| 超碰aⅴ人人做人人爽欧美| 国产欧美在线一区| 97视频在线观看视频免费视频| 欧美视频第一页| 亚洲区第一页| 亚洲一区二区电影| 骚视频在线观看| 91看片淫黄大片一级在线观看| 亚洲美女一区二区三区| 亚洲成年人影院在线| 欧美小视频在线| 欧美国产禁国产网站cc| 国产成人av在线影院| 精品色999| 小视频免费在线观看| 成人黄色片视频|