學習 mysql實戰45講 筆記(1~10),用於後期檢驗

僅供自己複習用

 

第一章 mysql的結構,和查詢語句流程

1. MySQL的框架有幾個組件, 各是什麼作用? 

 連接器,緩存器,分析器,優化器,執行器
2. Server層和存儲引擎層各是什麼作用?

server層提供核心組件的功能,同時提供視圖,執行過程等和一些函數操作,引擎層主要對應數據的操作

3. you have an error in your SQL syntax 這個保存是在詞法分析裏還是在語法分析裏報錯?

語法分析,詞法分析主要解析出sql語句中的字符串代表什麼意思

4. 對於表的操作權限驗證在哪裏進行?

執行器中

5. 執行器的執行查詢語句的流程是什麼樣的? 

比如要查詢數據name=張三的語句

1.調用數據引擎的查詢接口獲取第一行數據,判斷是不是張三,如果是則記錄到結果集

2.獲取下一行,執行上面的判斷,一直到最後一行.

3.將上面執行所有滿足條件的結果集返回給客戶端.

針對索引也是差不多的,第一次取滿足條件的第一行,之後取滿足條件的下一行.

 

第二章 redolog binlog 修改語句執行流程

1. redo log的概念是什麼? 爲什麼會存在.

重做日誌,redolog是對記錄修改之後的物理日誌,記錄的是數據頁的物理修改,而不是某一行或某幾行修改成怎樣怎樣,它用來崩潰恢復提交後的物理數據頁(恢復數據頁,且只能恢復到最後一次提交的位置)。記錄格式(數據文件、數據頁、數據行、操作類型、操作值)

正常mysql修改數據時,要將操作寫入磁盤,然後磁盤每次也需要找到對應的那條數據,這樣io成本過高,當有數據更新操作時,innodb會先將數據記錄在redo log中,並更新內存,在合適的時間再將操作寫入磁盤.這裏要注意 寫數據不是把redo log寫入,redolog只是爲了保證crash safe,真正刷數據還是把內存中的髒頁刷進去

.

redo log並沒有記錄數據頁的完整數據,所以它並沒有能力自己去更新磁盤數據頁

如果是正常運行的實例的話,數據頁被修改以後,跟磁盤的數據頁不一致,稱爲髒頁。最終數據落盤,就是把內存中的數據頁寫盤。這個過程,甚至與redo log毫無關係。

在崩潰恢復場景中,InnoDB如果判斷到一個數據頁可能在崩潰恢復的時候丟失了更新,就會將它讀到內存,然後讓redo log更新內存內容。更新完成後,內存頁變成髒頁,就回到了第一種情況的狀態。

 

redo log是固定大小的,從頭開始寫,當寫到末尾時會循環重頭再來,其中存在write pos代表當前記錄位置,同時ckeckpoint記錄當前要擦除的位置,系統空閒時會將部分redolog操作記錄到硬盤,同時更新checkpoint.

(

關於順序寫和隨機寫

第一種:假設我們所需要的數據是隨機分散在磁盤的不同頁的不同扇區中的,那麼找到相應的數據需要等到磁臂(尋址作用)旋轉到指定的頁,然後盤片尋找到對應的扇區,才能找到我們所需要的一塊數據,一次進行此過程直到找完所有數據,這個就是隨機IO,讀取數據速度較慢。

第二種:假設我們已經找到了第一塊數據,並且其他所需的數據就在這一塊數據後邊,那麼就不需要重新尋址,可以依次拿到我們所需的數據,這個就叫順序IO。通俗點說就是追加寫

)

2. 什麼是WAL(write-ahead log)機制, 好處是什麼.

先記錄日誌,再記錄磁盤,執行事務的時候,寫完內存和日誌事務就算完成了,好處就是上面的redo log crash safe,同時,可以不需要每次更新都把內存中的數據實時刷入磁盤.減少IO

 

3. redo log 爲什麼可以保證crash safe機制.

crash safe,即當服務器突然斷電或宕機,需要保證已提交的數據或修改不會丟失,未提交的數據能夠自動回滾

Innodb通過Redo Log和Undo Log可以保證以上兩點。爲了保證嚴格的CrashSafe,必須要在每個事務提交的時候,將Redo Log寫入硬件存儲,通過redo日誌將所有已經在存儲引擎內部提交的事務應用redo log恢復到內存中.所有已經prepare但是沒有commit的transactions將會應用undo log做rollback


4. binlog的概念是什麼, 起到什麼作用, 可以做crash safe嗎? 

binlog是邏輯日誌。其中一種形式是記錄的原始sql語句,另一種形式是記錄row上的數據,比如update t set c = c +1 where id = 1; binlog是數據庫server層的。和數據是隔離開來的,他可以用來主從複製,和備份恢復數據庫用,他不能做到crash safe,

binlog沒有能力恢復“數據頁”

假設數據先存入,再記錄binlog,存入後mysql崩潰,此時數據庫中有數據,而binlog中沒有,反之,先記錄binlog再提交事務,記錄binlog後mysql崩潰,此時binlog比數據庫中多出一條數據


5. binlog和redolog的不同點有哪些? 

binlog屬於數據引擎的上層server層,redolog是屬於數據引擎層

redo log是物理日誌,記錄的是“在某個數據頁上做了什麼修改”;binlog是邏輯日誌,記錄的是這個語句的原始邏輯,比如“給ID=2這一行的c字段加1 ”。

redo log是循環寫的,空間固定會用完;binlog是可以追加寫入的。“追加寫”是指binlog文件寫到一定大小後會切換到下一個,並不會覆蓋以前的日誌。


7. 執行器和innoDB在執行update語句時候的流程是什麼樣的?

執行器先去找數據引擎要需要更新的行,引擎查找該行,如果改行數據頁在內存中則直接返回給執行器,如果不在則從硬盤中讀到內存,然後再返回

執行器拿到引擎給的行數據,將數據修改,得到這行新數據,再調用引擎接口寫入這行的新數據

引擎將這行更新到內存中,此時sql相當於執行成功會生成redo和undo的內存日誌

此時redo log處於準備階段 會被刷入磁盤持久化,然後告訴執行器執行完成,隨時可以提交事務

執行器記錄binlog,並記錄該日誌到磁盤(這裏就確定了事務肯定會提交,不然就會執行回滾操作,而不是記錄binlog日誌)

執行器調用引擎的提交事務接口完成事務提交,把剛剛寫入的redolog改爲提交狀態,同時事務結束了,刪除undo日誌(當然刪除前會看有沒有其他事務需要用到該undo日誌),更新完成

這一篇寫的不錯講解undo日誌


8. 如果數據庫誤操作, 如何執行數據恢復?

binlog會記錄所有的邏輯操作,並且是採用“追加寫”的形式

同時系統會定期做整庫備份。這裏的“定期”取決於系統的重要性,可以是一天一備,也可以是一週一備

首先,找到最近的一次全量備份

然後,從備份的時間點開始,將備份的binlog依次取出來,重放到誤刪表之前的那個時刻。


9. 什麼是兩階段提交, 爲什麼需要兩階段提交, 兩階段提交怎麼保證數據庫中兩份日誌間的邏輯一致性?

爲了保證redo log 和 bin log的一致性

如果時刻A的地方,也就是寫入redo log 處於prepare階段之後、寫binlog之前,發生了崩潰(crash),由於此時binlog還沒寫,redo log也還沒提交,所以崩潰恢復的時候,這個事務會回滾。這時候,binlog還沒寫,所以也不會傳到備庫\

如果在時刻B,也就是binlog寫完,redo log還沒commit前發生crash

如果redo log裏面的事務是完整的,也就是已經有了commit標識,則直接提交;

如果redo log裏面的事務只有完整的prepare,則判斷對應的事務binlog是否存在並完整:
a. 如果是,則提交事務;
b. 否則,回滾事務。

MySQL怎麼知道binlog是完整的?

  • statement格式的binlog,最後會有COMMIT;
  • row格式的binlog,最後會有一個XID event。

redo log 和 binlog是怎麼關聯起來的

它們有一個共同的數據字段,叫XID。崩潰恢復的時候,會按順序掃描redo log:

  • 如果碰到既有prepare、又有commit的redo log,就直接提交;
  • 如果碰到只有parepare、而沒有commit的redo log,就拿着XID去binlog找對應的事務。

 

第三章  事務隔離性

1、事務的特性:原子性、一致性、隔離性、持久性
2、多事務同時執行的時候,可能會出現的問題:髒讀、不可重複讀、幻讀
3、事務隔離級別:讀未提交、讀提交、可重複讀、串行化
4、不同事務隔離級別的區別:
讀未提交:一個事務還未提交,它所做的變更就可以被別的事務看到
讀提交:一個事務提交之後,它所做的變更纔可以被別的事務看到
可重複讀:一個事務執行過程中看到的數據是一致的。未提交的更改對其他事務是不可見的
串行化:對應一個記錄會加讀寫鎖,出現衝突的時候,後訪問的事務必須等前一個事務執行完成才能繼續執行
5、配置方法:啓動參數transaction-isolation
6、事務隔離的實現:每條記錄在更新的時候都會同時記錄一條回滾操作。同一條記錄在系統中可以存在多個版本,這就是數據庫的多版本併發控制(MVCC)。
7、回滾日誌什麼時候刪除?系統會判斷當沒有事務需要用到這些回滾日誌的時候,回滾日誌會被刪除。
8、什麼時候不需要了?當系統裏麼有比這個回滾日誌更早的read-view的時候。
9、爲什麼儘量不要使用長事務。長事務意味着系統裏面會存在很老的事務視圖,在這個事務提交之前,回滾記錄都要保留,這會導致大量佔用存儲空間。除此之外,長事務還佔用鎖資源,可能會拖垮庫。
10、事務啓動方式:一、顯式啓動事務語句,begin或者start transaction,提交commit,回滾rollback;二、set autocommit=0,該命令會把這個線程的自動提交關掉。這樣只要執行一個select語句,事務就啓動,並不會自動提交,直到主動執行commit或rollback或斷開連接。
11、建議使用方法一,如果考慮多一次交互問題,可以使用commit work and chain語法。在autocommit=1的情況下用begin顯式啓動事務,如果執行commit則提交事務。如果執行commit work and chain則提交事務並自動啓動下一個事務。

 

第四章 索引常見數據結構

.1.索引的作用:提高數據查詢效率
2.常見索引模型:哈希表、有序數組、搜索樹
3.哈希表:鍵 - 值(key - value)。
4.哈希思路:把值放在數組裏,用一個哈希函數把key換算成一個確定的位置,然後把value放在數組的這個位置
5.哈希衝突的處理辦法:鏈表
6.哈希表適用場景:只有等值查詢的場景
7.有序數組:按順序存儲。查詢用二分法就可以快速查詢,時間複雜度是:O(log(N))
8.有序數組查詢效率高,更新效率低
9.有序數組的適用場景:靜態存儲引擎。
10.二叉搜索樹:每個節點的左兒子小於父節點,父節點又小於右兒子
11.二叉搜索樹:查詢時間複雜度O(log(N)),更新時間複雜度O(log(N))
12.數據庫存儲大多不適用二叉樹,因爲樹高過高,會適用N叉樹
13.InnoDB中的索引模型:B+Tree
14.索引類型:主鍵索引、非主鍵索引
主鍵索引的葉子節點存的是整行的數據(聚簇索引),非主鍵索引的葉子節點內容是主鍵的值(二級索引)
15.主鍵索引和普通索引的區別:主鍵索引只要搜索ID這個B+Tree即可拿到數據。普通索引先搜索索引拿到主鍵值,再到主鍵索引樹搜索一次(回表)
16.一個數據頁滿了,按照B+Tree算法,新增加一個數據頁,叫做頁分裂,會導致性能下降。空間利用率降低大概50%。當相鄰的兩個數據頁利用率很低的時候會做數據頁合併,合併的過程是分裂過程的逆過程。
17.從性能和存儲空間方面考量,自增主鍵往往是更合理的選擇。

 

第五章  回表 覆蓋索引

回表:回到主鍵索引樹搜索的過程,稱爲回表

左圖是主鍵索引,右圖是非主鍵索引,主鍵索引葉子節點上是數據行,非主鍵索引葉子節點上是改行數據的主鍵.

比如要通過K字段作爲條件,查詢一個非主鍵列,則需要先查詢到主鍵,在用主鍵回表到主鍵索引上查詢到整行數據

 

覆蓋索引:某索引已經覆蓋了查詢需求,稱爲覆蓋索引,例如:select ID from T where k between 3 and 5
這裏因爲主鍵ID在k索引上,所以覆蓋了查詢需求,所以不需要回表.

如果不光查詢ID,還需要查詢另一個字段u 可以考慮把 k u作爲聯合索引,這樣他們也會變成覆蓋索引,避免回表查詢


最左前綴原則:B+Tree這種索引結構,可以利用索引的"最左前綴"來定位記錄
只要滿足最左前綴,就可以利用索引來加速檢索。
最左前綴可以是聯合索引的最左N個字段,也可以是字符串索引的最左M個字符
第一原則是:如果通過調整順序,可以少維護一個索引,那麼這個順序往往就是需要優先考慮採用的。
索引下推:在MySQL5.6之前,只能從根據最左前綴查詢到ID開始一個個回表。到主鍵索引上找出數據行,再對比字段值。
MySQL5.6引入的索引下推優化,可以在索引遍歷過程中,對索引中包含的字段先做判斷,直接過濾掉不滿足條件的記錄,減少回表次數。

 

第六章  全局鎖,表級鎖(表鎖,mdl鎖)

1.Mysql中的鎖分類

全局鎖,表級鎖,行級鎖

2.什麼是全局鎖,全局讀鎖怎麼加,使用場景是什麼?會出現什麼問題

全局鎖就是對整個數據庫實例加鎖

全局讀鎖就是讓整個數據庫處於只讀狀態,其他的增刪改及數據庫結構修改語句都會被阻塞

語句是:Flush tables with read lock

全局鎖的使用場景就是 給整個數據庫做邏輯備份,也就是把整個庫裏每個表都select出來存成文檔.如果在主庫上備份會使業務停擺,在整個備份期間,增刪改不可用.如果在從庫備份,,備份期間從庫不能接收來自主庫的binlog會導致主從延遲.

3.官方自帶的邏輯備份工具是什麼,如何不使用全局鎖做邏輯備份

官方使用的是mysqldump,他和全局鎖不一樣,mysqldump使用參數-single-transaction的時候,導數據之前會啓動一個事務,來確保拿到一致性視圖,(使用mvcc,和隔離級別可重複讀一樣),在此期間數據是可以更新的.

之所以還是要有全局鎖是因爲mysqldump需要事務的支持,如果數據庫中存在myISAM這種不支持事務的表時 則不可用

4.什麼是表級鎖

mysql中表級鎖有兩種,一種是表鎖,一種是元數據鎖(mete data lock,MDL)

表鎖的語句是  lock tables 表名 read/write 表鎖即會限制別的線程的讀寫,也會限制本線程的讀寫對象

例如 線程A 執行 lock tables t1 read ,t2 write,線程B 其他線程寫t1,讀寫t2都會阻塞,同時線程A也只能讀t1,讀寫t2,同時也不能訪問其他表

主要用來處理併發

元數據鎖(MDL):MDL並不需要顯示使用,在訪問一個表的時候會自動加上,當對一個表進行增刪改查時,會加MDL讀鎖,當對一個表做結構變更時會加寫鎖

讀鎖不互斥,所以多個線程可以對一個表做增刪改查

讀鎖和血鎖互斥,寫鎖之間互斥,所以修改數據時,如果兩個線程同時修改一個表的結構,其中一個會阻塞(寫鎖互斥),而如果一個線程在讀一張表的時候,另一個線程修改該表結構的操作會被阻塞(讀鎖,寫鎖互斥)

5.MDL鎖導致的問題

上圖中線程A開啓事務以後獲取讀鎖,提交事務纔會釋放讀鎖,在此期間線程C添加表字段,阻塞,後續線程繼續查詢數據獲取讀鎖,也會阻塞,假設該表讀寫頻繁,且有重試機制,這個庫的線程很快就會爆滿

6.如果你要變更的表是一個熱點表,雖然數據量不大,但是上面的請求很頻繁,而你不得不加個字段,你該怎麼做

alter table語句裏設置等待時間,拿到mdl寫鎖就修改,不能拿到就放棄,避免阻塞後續語句,然後再重複這個指令.

 

第七章 行級鎖,兩階段鎖協議,死鎖,死鎖檢測

1.什麼是行鎖
行鎖就是針對數據行加鎖,比如事務A修改了一行數據,同時事務B也要修改同一行,在事務A提交之前,事務B將阻塞.

2.什麼是兩階段鎖協議,有什麼用

在InnoDB事務中,行鎖是在需要是才添加的,但並不是不需要了就立刻釋放,而是等到事務結束後才釋放,這就是兩階段鎖協議.

如果你的事務中需要鎖多個行,要把最可能造成鎖衝突、最可能影響併發度的鎖儘量往後放。

比如線程A要修改行1,新增數據,線程B要修改行1,此時,線程A應該先新增數據,在修改行1,這樣就減少了衝突的時間.

3.死鎖

當系統不同線程出現循環資源依賴,涉及的線程都在等待別的線程釋放資源時,就會導致這幾個線程都進入無限等待的狀態,稱爲死鎖

4.怎麼處理死鎖

一種策略是,直接進入等待,直到超時。這個超時時間可以通過參數innodb_lock_wait_timeout來設置。

在InnoDB中,innodb_lock_wait_timeout的默認值是50s,意味着如果採用第一個策略,當出現死鎖以後,第一個被鎖住的線程要過50s纔會超時退出,然後其他線程纔有可能繼續執行,但是,我們又不可能直接把這個時間設置成一個很小的值,比如1s。這樣當出現死鎖的時候,確實很快就可以解開,但如果不是死鎖,而是簡單的鎖等待呢?所以,超時時間設置太短的話,會出現很多誤傷。

所以我們一般採用第二種

另一種策略是,發起死鎖檢測,發現死鎖後,主動回滾死鎖鏈條中的某一個事務,讓其他事務得以繼續執行。將參數innodb_deadlock_detect設置爲on,表示開啓這個邏輯。

主動死鎖檢測,innodb_deadlock_detect的默認值本身就是on。主動死鎖檢測在發生死鎖的時候,是能夠快速發現並進行處理的,但是它也是有額外負擔的。

每當一個事務被鎖的時候,就要看看它所依賴的線程有沒有被別人鎖住,如此循環,最後判斷是否出現了循環等待,也就是死鎖。

每個新來的被堵住的線程,都要判斷會不會由於自己的加入導致了死鎖,這是一個時間複雜度是O(n)的操作。假設有1000個併發線程要同時更新同一行,那麼死鎖檢測操作就是100萬這個量級的。雖然最終檢測的結果是沒有死鎖,但是這期間要消耗大量的CPU資源。因此,你就會看到CPU利用率很高,但是每秒卻執行不了幾個事務。

一個思路是控制併發度。根據上面的分析,你會發現如果併發能夠控制住,比如同一行同時最多隻有10個線程在更新,那麼死鎖檢測的成本很低,就不會出現這個問題,這個併發控制要做在數據庫服務端。如果你有中間件,可以考慮在中間件實現

 

什麼是共享鎖和排他鎖

共享鎖又叫做讀鎖,所有的事務只能對其進行讀操作不能寫操作,加上共享鎖後在事務結束之前其他事務只能再加共享鎖,除此之外其他任何類型的鎖都不能再加了。

用法:SELECT `id` FROM  table WHERE id in(1,2) LOCK IN SHARE MODE 結果集的數據都會加共享鎖

排他鎖:若某個事物對某一行加上了排他鎖,只能這個事務對其進行讀寫,在此事務結束之前,其他事務不能對其進行加任何鎖,其他進程可以讀取,不能進行寫操作,需等待其釋放。

用法:SELECT `id` FROM mk_user WHERE id=1 FOR UPDATE

注意:由於在innodb中行鎖,他是針對索引去鎖定該條數據,而不是直接鎖定該條數據的。

 

第八章 MVCC undolog 一致性視圖 快照讀,當前讀

1.innodb支持RC和RR隔離級別實現是用的一致性視圖(consistent read view)

2.事務在啓動時會拍一個快照,這個快照是基於整個庫的.
基於整個庫的意思就是說一個事務內,整個庫的修改對於該事務都是不可見的(對於快照讀的情況)
如果在事務內select t表,另外的事務執行了DDL t表,根據發生時間,要嘛鎖住要嘛報錯(參考第六章)

 

3.什麼是undo_log

每條記錄在更新的時候都會同時記錄一條回滾操作。記錄上的最新值,通過回滾操作,都可以得到前一個狀態的值。這個回滾記錄就是回滾日誌undo_log

如圖三個虛線箭頭,就是undo log 分別是u1 u2 u3 通過回滾日誌可以找到這行記錄的歷史版本,當沒有事務再需要用到這些回滾日誌時,回滾日誌會被刪除。


4.事務是如何實現的MVCC呢?
(1)每個事務都有一個事務ID,叫做transaction id(嚴格遞增)

 (2)InnoDB爲每個事務構造了一個數組,用來保存這個事務啓動瞬間,當前正在“活躍”的所有事務ID。“活躍”指的就是,啓動了但還沒提交。數組裏面事務ID的最小值記爲低水位,當前系統裏面已經創建過的事務ID的最大值加1記爲高水位。(這裏我理解成當前這個事務的ID就是高水位,因爲他現在創建事務,分配給他的事務ID就是在之前的事務ID上遞增1)

這個視圖數組和高水位,就組成了當前事務的致性視圖(read-view)

而數據版本的可見性規則,就是基於數據的row trx_id和這個一致性視圖的對比結果得到的。

這樣,對於當前事務的啓動瞬間來說,一個數據版本的row trx_id,有以下幾種可能:

如果落在綠色部分,表示這個版本是已提交的事務或者是當前事務自己生成的,這個數據是可見的;

如果落在紅色部分,表示這個版本是由將來啓動的事務生成的,是肯定不可見的;

如果落在黃色部分,那就包括兩種情況
a. 若 row trx_id在數組中,表示這個版本是由還沒提交的事務生成的,不可見;
b. 若 row trx_id不在數組中,表示這個版本是已經提交了的事務生成的,可見。

 

一個數據版本,對於一個事務視圖來說,除了自己的更新總是可見以外,有三種情況:

  • 版本未提交,不可見;
  • 版本已提交,但是是在視圖創建後提交的,不可見;
  • 版本已提交,而且是在視圖創建前提交的,可見。

這裏的數據版本如下圖的當前版本 版本1 版本2,事務視圖指的是當前這個事務的視圖數組如下的[99 ,100]

  • (1,3)還沒提交,屬於情況1,不可見;
  • (1,2)雖然提交了,但是是在視圖數組創建之後提交的,屬於情況2,不可見;
  • (1,1)是在視圖數組創建之前提交的,可見。

更新數據都是先讀後寫的,而這個讀,只能讀當前的值,稱爲“當前讀”(current read)

除了update語句外,select語句如果加鎖,也是當前讀。

 

5.讀提交的邏輯和可重複讀的邏輯類似,它們最主要的區別是是什麼

  • 在可重複讀隔離級別下,只需要在事務開始的時候創建一致性視圖,之後事務裏的其他查詢都共用這個一致性視圖;
  • 在讀提交隔離級別下,每一個語句執行前都會重新算出一個新的視圖。

 

第九章 普通索引 唯一索引選擇 change buffer

1.選擇普通索引還是唯一索引?
對於查詢過程來說
a、普通索引,查到滿足條件的第一個記錄後,繼續查找下一個記錄,知道第一個不滿足條件的記錄
b、唯一索引,由於索引唯一性,查到第一個滿足條件的記錄後,停止檢索
但是,兩者的性能差距微乎其微。因爲InnoDB根據數據頁來讀寫的。也就是說基本上多出來的查詢只是在內存上找速度快


對於更新過程來說:
概念:

change buffer
當需要更新一個數據頁,如果數據頁在內存中(buffer pool)就直接更新,如果不在內存中,在不影響數據一致性的前提下,InnoDB會將這些更新操作緩存在change buffer中。下次查詢需要訪問這個數據頁的時候,將數據頁讀入內存,然後執行change buffer中的與這個頁有關的操作。
change buffer是可以持久化的數據。在內存中有拷貝,也會被寫入到磁盤上

merge:將change buffer中的操作應用到原數據頁上,得到最新結果的過程,成爲merge
訪問這個數據頁會觸發merge,系統有後臺線程定期merge,在數據庫正常關閉的過程中,也會執行merge

唯一索引的更新不能使用change buffer,因爲先要唯一性校驗,這個過程得把數據頁取到內存,這個時候直接跟新內存就好,沒必要change buffer

change buffer用的是buffer pool裏的內存,change buffer的大小,可以通過參數innodb_change_buffer_max_size來動態設置。這個參數設置爲50的時候,表示change buffer的大小最多隻能佔用buffer pool的50%。

將數據從磁盤讀入內存涉及隨機IO的訪問,是數據庫裏面成本最高的操作之一。 
change buffer 因爲減少了隨機磁盤訪問,所以對更新性能的提升很明顯。

change buffer使用場景
在一個數據頁做merge之前,change buffer記錄的變更越多,收益就越大。
對於寫多讀少的業務來說,頁面在寫完以後馬上被訪問到的概率比較小,此時change buffer的使用效果最好。這種業務模型常見的就是賬單類、日誌類的系統。

反過來,假設一個業務的更新模式是寫入之後馬上會做查詢,那麼即使滿足了條件,將更新先記錄在change buffer,但之後由於馬上要訪問這個數據頁,會立即觸發purge過程。
這樣隨機訪問IO的次數不會減少,反而增加了change buffer的維護代價。所以,對於這種業務模式來說,change buffer反而起到了副作用。

索引的選擇和實踐:儘可能使用普通索引。

redo log 和change buffer的區別:
redo log主要節省的是隨機寫磁盤的IO消耗(轉成順序寫,相當於本來要查詢到該數據的數據頁,但是現在不用了,直接順序追加記錄在redolog日誌裏面),而change buffer主要節省的則是隨機讀磁盤的IO消耗(原本要更新的時候是要先找到數據頁,現在不讀數據頁了,直接記錄在changebuffer中)。

流程如下

1.Page 1在內存中,直接更新內存;

2.Page 2沒有在內存中,就在內存的change buffer區域,記錄下“我要往Page 2插入一行”這個信息

3.將上述兩個動作記入redo log中(圖中3和4)。

 

第十章.MySQL爲什麼有時候會選錯索引

現象:優化器存在選錯索引的可能性

主要的原因是,優化器對不同索引執行代價的判斷出現了問題,

比如我們平時在大量刪除數據後,索引其實是沒有刪除掉的 ,會導致優化器在選擇索引的時候錯誤的判斷了使用不同索引需要的行數

對於由於索引統計信息不準確導致的問題,你可以用analyze table來解決。

 

再比如說 在排序語句中, 如果有兩個索引,A索引會掃描1000行,B索引會掃描5000行,但是B是需要排序的字段這個時候,優化器會選擇B索引,雖然行數增加了,但是由於B索引本身是有序的,此時優化器認爲可以節省排序的時間,依然會使用B索引

而這些優化器誤判的情況,你可以在應用端用force index來強行指定索引,也可以通過修改語句來引導優化器,還可以通過增加或者刪除索引來繞過這個問題。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章