一:MySql架構
1.一條sql語句如何執行的:mysql5.7查詢緩存默認關閉,mysql8緩存已被移除。
- 存儲引擎對比:
MySIAM:表級鎖定,不支持事務,已讀為主
InnoDB:支持事務,支持外鍵,支持行級別和表級別的鎖定,B+索引,效率高
Memory:內存存儲。
Archive:用於存儲和檢索大量很少引用的歷史、存檔、安全審計信息,不支持事務。
- mysql架構
局部性原理:讀取磁盤的數據,它附近的數據也會被讀取到內存,操作形同一般4k,mysql中讀取每頁的數據16k,Innodb設置了一個內存叫Buffer Pool,默認128M,讀取數據時先去buffer中讀取,寫數據也是先寫到buffer中,為了不產生臟頁,innodb有專門的后台線程把buffer中的數據寫到磁盤中,這個動作叫刷臟。為了防止數據庫宕機造成數據不一致,Innodb會把修改操作寫到Redo log(重做日志)中,事務的acid的持久化就是這個日志實現的,(為啥不直接寫到磁盤,因為寫磁盤的數據不是連續的,io效率低,日志是順序的,快速。)redo log大小是固定的,一旦寫滿,就會觸發buffer到磁盤的同步。和redo log 還有一個undo log 是重做日志,記錄的修改之前的數據,用於回滾。
6.redo log 和undo log是innodb獨有的,mysql的server層也有一個日志叫Binlog可以被所有存儲引擎使用,binlog以事件的形式記錄所有ddl和dml語句,比如給id=1的count字段加1,binlog記錄的是操作不是數據值,屬於邏輯日志。
Binlog用於1.主從復制2數據恢復。
7.mysql主從復制原理:從服務器讀取主服務器的binlog,在執行一次。
7.一條更新語句的執行(省略了undo log)
Redo兩階段是為了防止寫入binlog失敗。
二:MySql索引原理
- 為何需要索引
數據是以文件存儲在磁盤,查詢的時候不能挨個查找數據,有了索引直接可以找到該數據所在的位置
- InnoDB索引類型:普通索引,唯一索引,主鍵索引,聚集索引
聚集索引:索引鍵值的邏輯順序和表數據行的物理存儲順序一致,主鍵索引就是一種聚集索引。
3.InnoDB索引采用B+樹
4.聚集索引的葉子節點存儲的數據行。二級索引(非聚集索引)葉子節點存儲的是索引字段和所在行的主鍵字段,當查詢一個name的二級索引時,先找到二級索引中葉子節點name的主鍵id值,然后在主鍵索引中查找id的葉子結點,葉子結點存儲的就是數據行的數據。
》如果定義了主鍵,主鍵就作為聚集索引,
》如果沒有定義主鍵索引的話,InnoDB會選擇第一個不包含NULL的唯一索引作為主鍵索引,
》如果這個唯一也沒有,InnoDB會選擇一個6字節的ROWID字段作為隱藏的聚集索引,會隨着記錄的寫入而作為主鍵遞增。
5.聯合索引:多個字段作為一個索引,最左匹配,
6.覆蓋索引:如果select的數據在二級索引的節點就能找到就不會再去主鍵索引中查找。
7.回表:查詢二級索引,再根據二級索引的數據到主鍵索引去查詢數據叫回表
8.在什么字段上建立索引
Wher
9.什么時候索引會失效
》索引列上使用函數(replace substr concat sum count avg)表達式、計算等
》字符串不加引號 where name=123
》like條件中前面帶%
》NOT LIKE 查詢
》!= <> not in在某些條件下可以使用索引
三:MySql事務和鎖機制
- 事務四大特性;ACID
原子性:事務要么成功,要么失敗
一致性:數據前后保持一致
隔離性:多個事務之間是相互隔離,互不影響的
持久性:只要事務操作成功,不會因為數據庫宕機等外界因素恢復到原來的狀態(redo log實現)
- 事務並發問題
臟讀:事務A讀到事務B還未提交的數據
不可重復讀:事務A讀到事務B已提交的數據,前后數據不一致。
幻讀:事務A讀取的數據是事務B插入了新行。
- 事務隔離級別:
未提交讀:沒解決任何問題
已提交讀:解決了臟讀
可重復讀:解決了臟讀和不可重復讀
串行化:三個問題都解決了
- InnoDB堆事務隔離級別的支持
- InnoDB的兩大實現方法
5.1 LBCC:讀取數據的時候鎖定數據,鎖的並發控制
5.2 MVCC:修改數據的時候建立一個快照,多版本的並發控制
Mvcc實現的原理:我可以查到在我這個事務修改的數據或者我這個事務開始之前已經存在並提交的數據,在我這個事務之后新增修改的數據我是查不到的。
Innodb給每行記錄增加三個字段:
創建版本號:插入或更新行的最后一個事務id
刪除版本號:數據被刪除或標志為舊數據的事務id
Rowed:主鍵id
- 鎖的分類
》共享鎖:slect 。。lock in share mode
》排他鎖:一個事務獲取了一行數據的排它鎖,其他事務就不能再獲取這一行數據的共享鎖或者排他鎖,但不表示不能讀數據,比如select * from a where name=‘2’ 這個select是不會加任何鎖的,所以不會阻塞。Update delete 會自動加排它鎖
》意向鎖:給一行數據加上共享鎖之前,數據庫會自動給這張表加上意向共享鎖,同樣的,給一行數據加上排他鎖之前,數據庫會自動給這張表加上意向排他鎖,這樣其他事務就不用每行遍歷查看數據是否有共享或者排它鎖。提高效率。
- 行鎖的原理:是給索引加鎖。
》如果有二級索引的話,會通過二級索引查找聚集索引。鎖住索引對應的記錄。表如果沒有索引,我們知道會創建一個隱藏的rowid作為聚集索引,查詢的時候因為沒創建索引,所以會全表查詢,這樣就鎖住了所有的隱藏rowid索引,所以外界看來就是整張表鎖住了。
- 鎖的算法。比如 id建立唯一索引 有 1 4 7 10 數據
》記錄鎖 :當使用唯一索引(唯一索引和主鍵索引)使用等值查詢,精確匹配到一條記錄的時候,使用的就是記錄鎖,比如 where id=1
》間隙鎖:查詢的記錄不存在,無論等值查詢還是范圍查詢,使用的都是間隙鎖,比如:where id>4 and id <7 或者 where id=6 鎖住的(4,7] ,間隙鎖是左開右閉。
》臨鍵鎖:當使用范圍查詢,不僅命中了記錄,還包含了間隙鎖,這使用的就是臨鍵鎖,相當於記錄鎖加上間隙鎖,比如where id>5and id<9 ,命中了7,臨建鎖鎖住的是最后一個key的下一個左開右閉區間,所以鎖住了(4,10]。
- innodb各隔離級別的實現方式
四:MySql優化
- 服務器配置的優化
- Mysql配置的優化,連接數的設置等。
- 架構的優化:使用redis緩存,集群,主從復制,分庫分表
- Sql的優化:慢查詢日志分析,分析mysql運行狀態,explain分析sql,看看查詢順序、查詢type類型(system>const>eq_ref>ref>range>index>all 至少達到range范圍索引),可能用到的索引,掃描行數,extra信息,優化sql語句,比如使用索引,
- 存儲引擎的選擇,常規的innodb,查詢多的myisam,臨時數據多的memory,表結構的構建,字段的類型選擇,比如性別用tinyint,varchar代替char,不要使用外鍵,觸發器,視圖等,不要使用數據庫存圖片。
- 代碼的優化,降級限流,消息隊列等等,盡量減輕數據庫壓力。