1.事務(wù)隔離級(jí)別
ACID
原子性:undo log
一致性:最核心本質(zhì)的要求
隔離性:鎖+mvcc
持久性:redo log
讀未提交
讀已提交:不可重復(fù)讀衅谷,前后2次讀取的數(shù)據(jù)有變化
可重復(fù)讀:兩次快照讀杜恰,讀到的數(shù)據(jù)一樣扛门。會(huì)有幻讀現(xiàn)象:如果讀一個(gè)區(qū)間,發(fā)現(xiàn)多出一條數(shù)據(jù)挚币。其實(shí)mysql沒有幻讀了,如果幻讀要求2次讀都是快照讀的話。
序列化:所有事務(wù)依次執(zhí)行鸯屿。
2.MVCC
數(shù)據(jù)庫讀分2種,當(dāng)前讀和快照讀把敢。mvcc多版本并發(fā)控制是指維持一個(gè)數(shù)據(jù)多個(gè)版本寄摆,使得讀寫不沖突。主要依賴表的幾個(gè)隱藏字段(DB_TRX_ID, DB_ROLL,DB_ROW_ID),undolog(記錄多版本)修赞,readview(快照)婶恼。
RR隔離級(jí)別,事務(wù)第一個(gè)快照讀生成readview視圖柏副,后續(xù)所有的快照讀都復(fù)用這個(gè)視圖勾邦。如果第二個(gè)是當(dāng)前讀,會(huì)更新操作行的readview視圖
RC隔離級(jí)別割择,事務(wù)中每一個(gè)快照讀都生成一個(gè)最新視圖眷篇,可以讀到別人提交的內(nèi)容。
3.mysql的幻讀是如何解決
事務(wù)1執(zhí)行快照讀age=20的記錄發(fā)現(xiàn)2條荔泳,事務(wù)2執(zhí)行插入age=20的記錄1條提交蕉饼。事務(wù)1更新age=20的記錄虐杯,發(fā)現(xiàn)更新3條(當(dāng)前讀)。事務(wù)1查詢age=20的記錄發(fā)現(xiàn)3條昧港。這就是mysql的幻讀擎椰,其實(shí)這不是嚴(yán)格意義的幻讀。如果要解決的話创肥,快照讀變當(dāng)前讀for update加間隙鎖达舒。
4.sql join原理
簡單嵌套遞歸(兩個(gè)表笛卡爾積匹配),索引驅(qū)動(dòng)遞歸嵌套(被驅(qū)動(dòng)表有索引叹侄,快速匹配)巩搏,批量遞歸嵌套(一次拿一批數(shù)據(jù)匹配)
5.說一下索引原理
索引是一顆B+樹,樹的高度夠低趾代,另外支持范圍查詢(B樹不支持范圍查詢)贯底。分為聚簇索引和非聚簇索引,聚簇索引一般以自增主鍵(方便預(yù)讀和插入的時(shí)候頁不會(huì)分裂)稽坤,非聚簇索引葉子節(jié)點(diǎn)存儲(chǔ)的主鍵丈甸,需要回到聚簇索引查找具體數(shù)據(jù)。
索引常見不生效場(chǎng)景:組合索引左匹配原則尿褪,like操作睦擂,函數(shù)轉(zhuǎn)換,or操作等杖玲。(思考一下索引結(jié)構(gòu)顿仇,就知道是否能夠走索引)
6. mysql主從同步原理
主寫binlog 通過io thread同步到從,從寫到relay log(順序?qū)懀┌诼恚瑥牡膕ql thread執(zhí)行relay log(隨機(jī)寫)臼闻。由于sql thread是單線程,如果主庫qps高囤采,會(huì)導(dǎo)致sql thread執(zhí)行不及時(shí)述呐,導(dǎo)致主從延遲。 mysql 5.7增加了mts并行復(fù)制技術(shù)(為什么sql thread是單線程蕉毯,因?yàn)橛行﹕ql是有先后執(zhí)行限制乓搬。如果事務(wù)提交的時(shí)候,判斷一組事務(wù)無先后限制代虾,可以組提交事務(wù)进肯。這樣這組組提交的事務(wù)到從庫也是可以并行執(zhí)行的。組提交還可以解決主庫bin log日志刷盤慢的問題)
7. 如何優(yōu)化sql棉磨,執(zhí)行計(jì)劃有哪些關(guān)鍵參數(shù)
type:訪問數(shù)據(jù)的方式江掩,index(索引),range(范圍查詢),index_merge(組合索引)环形,ref(非唯一索引進(jìn)行數(shù)據(jù)查找)策泣,key:使用的索引。
8. sql執(zhí)行過程
連接器-分析器-優(yōu)化器-執(zhí)行器斟赚,執(zhí)行器判斷sql類型着降,select和update會(huì)從磁盤讀數(shù)據(jù)到內(nèi)存差油,普通查詢通過mvcc查詢拗军,update,insert等會(huì)寫undolog(回滾)蓄喇,redo log和bin log(redo 和 bin會(huì)采取2階段提交发侵,保證數(shù)據(jù)最終一致性)
9. 說一下mysql的鎖
當(dāng)前讀需要加鎖(update,delete妆偏,insert刃鳄,for update),先加臨鍵鎖钱骂,如果是唯一索引且是等值查詢退化成行鎖叔锐。如果是非唯一索引且等值查詢,向右查到第一個(gè)大于等值查詢的值见秽,然后退化為間隙鎖愉烙。原則是要鎖住間隙和行。
10常見sql優(yōu)化場(chǎng)景
- 規(guī)避回表解取,覆蓋索引
- order by 規(guī)避fileSort步责,盡量用索引覆蓋排序字段
- join動(dòng)作,連接字段需要有索引禀苦,規(guī)避全量數(shù)據(jù)笛卡爾積蔓肯,盡量用inner join,小表去驅(qū)動(dòng)大表振乏。
LEFT JOIN A表為驅(qū)動(dòng)表
INNER JOIN MySQL會(huì)自動(dòng)找出那個(gè)數(shù)據(jù)少的表作用驅(qū)動(dòng)表
RIGHT JOIN B表為驅(qū)動(dòng)表
- group by字段如果無索引會(huì)在臨時(shí)表中計(jì)次蔗包,然后按照統(tǒng)計(jì)字段排序返回,如果不想排序 order by null慧邮。
- limit 10000调限,10,這樣的語句可以優(yōu)化成先查主鍵id
Select * from table limit 1000000, 10
Select * from table where id in (select pk from table limit 100000, 10)
- 子查詢改寫成臨時(shí)表模式:
示例:select id from t1 where num in(select id from t2 where id > 10)
此時(shí)外層查詢會(huì)全表掃描赋咽,不使用索引旧噪。可以修改為:
select id from t1,(select id from t1 where id > 10)t2 where t1.id = t2.id
- exist和in分場(chǎng)景使用
in是把外表和內(nèi)表作hash連接脓匿,而exists是對(duì)外表作loop循環(huán)淘钟,每次loop循環(huán)再對(duì)內(nèi)表進(jìn)行查詢,一直以來認(rèn)為exists比in效率高的說法是不準(zhǔn)確的陪毡。
如果查詢的兩個(gè)表大小相當(dāng)米母,那么用in和exists差別不大勾扭;如果兩個(gè)表中一個(gè)較小一個(gè)較大,則子查詢表大的用exists铁瞒,子查詢表小的用in妙色;
例如:表A(小表),表B(大表)
select * from A where cc in(select cc from B) -->效率低慧耍,用到了A表上cc列的索引身辨;
select * from A where exists(select cc from B where cc=A.cc) -->效率高,用到了B表上cc列的索引芍碧。
相反的:
select * from B where cc in(select cc from A) -->效率高煌珊,用到了B表上cc列的索引
select * from B where exists(select cc from A where cc=B.cc) -->效率低,用到了A表上cc列的索引泌豆。
- 用union all 不用union定庵,union會(huì)去重。