一沐旨、MySQL問答
1、數(shù)據(jù)庫sql語句查詢榨婆,跨表查詢有哪幾種方式
<p style="color:blue">內(nèi)連接(inner可以不寫)
select e.name e.age p.product_name p.saled
from employee e,product p
where e.id = p.id
select e.name e.age p.product_name p.saled
from employee inner
join e褒侧,product p on e.id = p.id
這就是內(nèi)連接良风,它要求數(shù)據(jù)必須On條件必須百分百匹配才會符合條件并返回。當(dāng)不滿足時闷供,他會返回空烟央。
外連接是用左\右側(cè)的數(shù)據(jù)去關(guān)聯(lián)另一側(cè)的數(shù)據(jù),即使關(guān)聯(lián)不上任何數(shù)據(jù)也得把左\右側(cè)的數(shù)據(jù)返回回來歪脏。
<p style="color:blue">外連接分(左外連接)和(右外連接)
<p style="color:blue">左外連接( left join)
select g2.Name疑俭,Price,ProductionDate婿失,Amount钞艇,g1.name
FROM Goods G1
left join GoodsType G2 on G1.Typeld=G2.IO
<p style="color:blue">右外連接(right join--空值的會顯示出來)
select g2.Name,Price豪硅,ProductionDate哩照,Amount,g1.name
FROM Goods G1 right join GoodsType G2 on G1.Typeld=G2.IO
<p style="color:blue">全外連接(full outer(可以不寫) join--空值的會顯示出來)
select g1.name懒浮,g2.Name飘弧,price,productiondate砚著,g2.Amount
FROM GoodsType g1 full outer join Goods g2 on g1.IO=g2.Typeld
<p style="color:blue">交叉連接(笛卡爾積)查詢所有的值
select g1.name次伶,g2.Name,price稽穆,productiondate冠王,g2.Amount
FROM GoodsType g1 cross join Goods g2 where g1.IO=g2.Typeld
2、數(shù)據(jù)庫的索引用到的是什么數(shù)據(jù)結(jié)構(gòu)秧骑?
答:B+樹
<p style="color:blue">問:那么B+樹的特點是什么版确?為什么要用這個數(shù)據(jù)結(jié)構(gòu)扣囊?
B+樹是B樹的變種,他們可以是 23樹绒疗,234樹侵歇,2345樹等等,當(dāng)單個節(jié)點允許伸出1200節(jié)點時吓蘑,三層就可以有17億惕虑,因此它體型扁平。磨镶。溃蔫。有利益磁盤IO
B+樹非葉子結(jié)點不存儲數(shù)據(jù),B樹存儲數(shù)據(jù)琳猫,所以相同大小數(shù)據(jù)塊伟叛,能存更多B+索引
B+樹葉子結(jié)點上有雙向鏈表串聯(lián),有利于進行范圍搜索
<p style="color:blue">B+樹為什么有利于磁盤IO脐嫂?
首先了解一下計算機的空間局部性原理:當(dāng)一個數(shù)據(jù)被用到時统刮,其附近的數(shù)據(jù)也通常會馬上被使用。即使只需要一個字節(jié)账千,磁盤也會從這個位置開始侥蒙,順序向后讀取一定長度的數(shù)據(jù)放入內(nèi)存。
使用紅黑樹(平衡二叉樹)結(jié)構(gòu)的話匀奏,每次磁盤預(yù)讀中的很多數(shù)據(jù)是用不上的數(shù)據(jù)鞭衩。因此,它沒能利用好磁盤預(yù)讀的提供的數(shù)據(jù)娃善。然后又由于深度大(較B樹而言)论衍,所以進行的磁盤IO操作更多。
B樹的每個節(jié)點可以存儲多個關(guān)鍵字会放,它將節(jié)點大小設(shè)置為磁盤頁的大小饲齐,充分利用了磁盤預(yù)讀的功能。每次讀取磁盤頁時就會讀取一整個節(jié)點咧最。也正因每個節(jié)點存儲著非常多個關(guān)鍵字捂人,樹的深度就會非常的小。進而要執(zhí)行的磁盤讀取操作次數(shù)就會非常少矢沿,更多的是在內(nèi)存中對讀取進來的數(shù)據(jù)進行查找滥搭。
B樹的查詢,主要發(fā)生在內(nèi)存中捣鲸,而平衡二叉樹的查詢瑟匆,則是發(fā)生在磁盤讀取中。因此栽惶,雖然B樹查詢查詢的次數(shù)不比平衡二叉樹的次數(shù)少愁溜,但是相比起磁盤IO速度疾嗅,內(nèi)存中比較的耗時就可以忽略不計了。因此冕象,B樹更適合作為索引代承。
<p style="color:blue">比B樹更適合作為索引的結(jié)構(gòu)是B+樹。MySQL中也是使用B+樹作為索引渐扮。它是B樹的變種论悴,因此是基于B樹來改進的。為什么B+樹會比B樹更加優(yōu)秀呢墓律?
B樹:有序數(shù)組+平衡多叉樹膀估。
B+樹:有序數(shù)組鏈表+平衡多叉樹。
B+樹的關(guān)鍵字全部存放在葉子節(jié)點中耻讽,這樣非葉子結(jié)點就能在相同的空間存儲更多的信息察纯,非葉子節(jié)點用來做索引,而葉子節(jié)點中有一個指針指向一下個葉子節(jié)點针肥。做這個優(yōu)化的目的是為了提高區(qū)間訪問的性能捐寥。而正是這個特性決定了B+樹更適合用來存儲外部數(shù)據(jù)。
3祖驱、mylsam、innodb的區(qū)別
1.InnoDB和MyISAM都是B+數(shù)的結(jié)構(gòu)瞒窒。
2.InnoDB采用MVCC來支持高并發(fā)捺僻,并且實現(xiàn)了四個標準的隔離級別。其默認級別是REPETABLE READ (可重復(fù)讀)崇裁,并且通過間隙鎖策略防止幻讀的出現(xiàn)匕坯。
3.InnoDB表是基于聚簇索引建立的。
4.InnoDB支持事務(wù)拔稳。
5.InnoDB具有自動崩潰恢復(fù)功能葛峻。
6.InnoDB支持外鍵。
MyISAM
1.MyISAM 不支持事務(wù)和行級鎖巴比。
2.崩潰后無法安全恢復(fù)术奖。
3.對于只讀的數(shù)據(jù),或者表比較小轻绞,可以忍受修復(fù)操作的可以使用采记。
4.MyISAM會將表存儲在兩個文件中,數(shù)據(jù)文件和索引文件政勃,分別以.MYD和.MYI為擴展名唧龄。
5.MyISAM 支持全文索引。
MyISAM | Innodb | |
---|---|---|
存儲結(jié)構(gòu) | 每張表被存放在三個文件:frm-表格定義奸远、MYD(MYData)-數(shù)據(jù)文件既棺、MYI(MYIndex)-索引文件 | 所有的表都保存在同一個數(shù)據(jù)文件中(也可能是多個文件讽挟,或者是獨立的表空間文件),InnoDB表的大小只受限于操作系統(tǒng)文件的大小丸冕,一般為2GB |
存儲空間 | MyISAM可被壓縮耽梅,存儲空間較小 | InnoDB的表需要更多的內(nèi)存和存儲,它會在主內(nèi)存中建立其專用的緩沖池用于高速緩沖數(shù)據(jù)和索引 |
可移植性晨仑、備份及恢復(fù) | 由于MyISAM的數(shù)據(jù)是以文件的形式存儲褐墅,所以在跨平臺的數(shù)據(jù)轉(zhuǎn)移中會很方便。在備份和恢復(fù)時可單獨針對某個表進行操作 | 免費的方案可以是拷貝數(shù)據(jù)文件洪己、備份 binlog妥凳,或者用 mysqldump,在數(shù)據(jù)量達到幾十G的時候就相對痛苦了 |
文件格式 | 數(shù)據(jù)和索引是分別存儲的答捕,數(shù)據(jù).MYD逝钥,索引.MYI | 數(shù)據(jù)和索引是集中存儲的,.ibd |
記錄存儲順序 | 按記錄插入順序保存 | 按主鍵大小有序插入 |
外鍵 | 不支持 | 支持 |
事務(wù) | 不支持 | 支持 |
鎖支持(鎖是避免資源爭用的一個機制拱镐,MySQL鎖對用戶幾乎是透明的) | 表級鎖定 | 行級鎖定艘款、表級鎖定,鎖定力度小并發(fā)能力高 |
SELECT | MyISAM更優(yōu) | |
INSERT沃琅、UPDATE哗咆、DELETE | InnoDB更優(yōu) | |
select count(*) | myisam更快,因為myisam內(nèi)部維護了一個計數(shù)器益眉,可以直接調(diào)取晌柬。 | |
索引的實現(xiàn)方式 | B+樹索引,myisam 是堆表 | B+樹索引郭脂,Innodb 是索引組織表 |
哈希索引 | 不支持 | 支持 |
全文索引 | 支持 | 不支持 |
4年碘、MySQL的Gtid復(fù)制原理是什么?
mysql主從復(fù)制原理就是主庫創(chuàng)建一個專門用于給從庫拉取binlog的賬號展鸡,并且給這個賬號授權(quán)屿衅,讓他可以拉取哪個DB的那個表的binlog,具體的授權(quán)SQL是:
grant repliacation slave on xx.xx to username@ip identify by 'password'
這樣從庫就能登陸主庫拉取binlog莹弊,那拉取binlog就得知道從哪個binlog的哪個位點拉取涤久,現(xiàn)有的有兩個方案:fileName + position 還有就是通過gtid自動找點。
<p style="color:blue">什么是GTID忍弛?原理拴竹?
https://www.cnblogs.com/ZhuChangwu/p/13040214.html
5、同步剧罩、半同步栓拜、異步復(fù)制原理是什么?
同步、半同步幕与、異步復(fù)制說的是 從庫在主庫上拉取binlog日志的模式挑势。
<p style="color:blue">同步:
主庫寫redolog 事物處于prepare狀態(tài)、主庫寫binlog啦鸣,然后從庫拉取binlog去回放潮饱,從庫回放成功后返回給主庫ack確認,所有的從庫都完成回放后主庫提交事物诫给。這樣是可以保證主從數(shù)據(jù)一致的但是缺點就是速度太慢了香拉。
<p style="color:blue">半同步:
主庫寫redolog 事物處于prepare狀態(tài)、主庫寫binlog中狂,然后從庫拉取binlog后返回給主庫ack凫碌,在眾多從庫中只要收到一個ack主庫就提交事物
<p style="color:blue">異步復(fù)制:
主庫根本不管從庫有沒有拉取回放binlog,直接寫redo胃榕、binlog盛险、然后提交事物
首先不允許出現(xiàn)主從數(shù)據(jù)不一致的情況:如果主從不一致對業(yè)務(wù)來說是有損的,一旦發(fā)生主從數(shù)據(jù)不一致的情況勋又,從庫就會出現(xiàn)斷開連接的可能苦掘。
6、說說你了解的MySQL慢查詢楔壤?
MySQL有監(jiān)控項:slow query 鹤啡, MySQL會將所有執(zhí)行時間超過閾值的SQL記錄到慢查日志中
我們的監(jiān)控系統(tǒng)可以監(jiān)控: 當(dāng)檢測到有慢查時觸發(fā)報警
通常出現(xiàn)慢查到情況如下:
1、表中的數(shù)據(jù)量很大蹲嚣,而且SQL的執(zhí)行沒有走索引
2揉忘、數(shù)據(jù)量太大了,即使走了索引依然超過了閾值
3端铛、大量的慢查占據(jù)MySQL連接,導(dǎo)致正常的SQL得不到連接執(zhí)行從而變成慢查SQL
4疲眷、優(yōu)化器選錯了索引
查看慢查時間閾值
mysql> show global variables like '%long_query_time%';
+-----------------+-----------+
| Variable_name | Value |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row inset (0.00 sec)
查看執(zhí)行時間最長的10條SQL
mysqldumpslow -s a1 -n 10 mysql.slow_log
推薦閱讀:https://mp.weixin.qq.com/s/tXTLMCiVpEnnmhUclYR19Q
7禾蚕、說說MySQL的執(zhí)行計劃
<p style="color:red">什么是執(zhí)行計劃
每次提交一個SQL到MySQL,MySQL內(nèi)核的查詢優(yōu)化器會針對這個SQL的語意生成一個執(zhí)行計劃狂丝,這個執(zhí)行計劃就代表了他會查哪些表换淆?用哪些索引,如何做排序和分組
<p style="color:red">執(zhí)行不同的sql有哪幾種情況
單表查詢舉例:
<p style="color:blue">示例1:
select * fromtablewhere id = x ;
select * fromtablewhere name = x ;
id是主鍵几颜、name是唯一索引像這種可以直接根據(jù)聚簇索引或者二級索引+回表就能查詢到我們想要的數(shù)據(jù)的方式在執(zhí)行計劃中稱為 const
要求二級索引必須是唯一索引倍试,才屬于const
<p style="color:blue">示例2:
select * fromtablewhere name = x ;
name是普通索引查詢的過程是:從name這個B+樹中查詢出一條記錄后,得到記錄的主鍵id蛋哭,然后去聚簇索引中回表县习,這種查詢方式速度也很快,在執(zhí)行計劃中叫:ref
<p style="color:blue">示例3:
select * fromtablewhere name = x and age = y and xx=yy ;
name、age躁愿、xx為普通索引這種sql要求where條件之后的SQL全得是等值比較叛本,在執(zhí)行計劃中才算做是ref
<p style="color:blue">示例4:
select * fromtablewhere name = x and name is NULL ;
name為普通索引這種sql就是在二級索引中同時搜索name = x和name = null的值,然后去主庫中回表彤钟。這種在執(zhí)行計劃中被稱為ref_or_null
<p style="color:blue">示例5:
select * fromtablewhere age >=x and age <=y
age是普通索引像這樣使用普通索引做范圍查詢来候,在執(zhí)行計劃中稱為 range
<p style="color:blue">示例6:index方式
index方式并不是說執(zhí)行計劃使用了索引,從聚簇索引中一路二分往下走逸雹。
假設(shè)有聯(lián)合索引:key(x1营搅,x2塘偎,x3)
查詢語句如下:
select x1肥矢,x2澎媒,x3 fromtablewhere x2=xxx;
想使用聯(lián)合索引得遵循左前綴原則辙诞,但是上面直接使用x2偏瓤,很顯然不符合左前綴原則摊滔,所以就用不上聯(lián)合索引勋篓,但是他查詢的x1咬扇、x2狮暑、x3其實對應(yīng)聯(lián)合索引中的x1鸡挠、x2、x3所以他會去掃描 聯(lián)合索引:key(x1搬男,x2拣展,x3)形成的B+樹,而不是全表掃描缔逛,在執(zhí)行計劃中這就做 index
所以說备埃,index其實是去遍歷二級索引,故他的效率肯定比ref褐奴,const按脚、ref_or_null慢,但是比全表掃描快一些
<p style="color:blue">示例7:all
比如你去查找數(shù)據(jù)但是不加where條件敦冬,就會進行全表掃描
<p style="color:blue">示例8:
select * fromtablewhere x1 = xxx or x2 >= yy ;
然后你的聯(lián)合索引是 key1(x1辅搬,x3) key2(x2,x4)
這時查詢優(yōu)化器只能在key1和key2中二選一使用脖旱,具體選哪一個就看使用哪個索引掃描行數(shù)少
比如使用x1掃描行數(shù)少堪遂,就先拿著x1去過濾一部分數(shù)據(jù)出來(ref的方式)然后去聚簇索引中回表查詢所有的數(shù)據(jù)在內(nèi)存中根據(jù)第二個條件x2 > yy 再過濾一次
<p style="color:blue">示例9:
select * fromtablewhere x1 = xxx and c1=xxx and c2 >= yy and c3 is null;
只有c1有索引查詢優(yōu)化器會根據(jù)x1,通過ref的方式查找到一批數(shù)據(jù)萌庆,然后去聚簇索引中回表溶褪,將所有符合條件的數(shù)據(jù)加載進內(nèi)存,然后在內(nèi)存中根據(jù)剩下的條件繼續(xù)過濾践险。
<p style="color:blue">示例10:
select * fromtablewhere x1 = xxx and x2=xxx;
x1和x2都有普通索引情況1: 查詢優(yōu)化器使用x1索引在二級索引中查詢中一批數(shù)據(jù)猿妈,然后將這些數(shù)據(jù)放到聚簇索引中回表吹菱,將數(shù)據(jù)所有字段查詢出來,然后在內(nèi)存中根據(jù)x2=xxx再過濾于游。
情況2:查詢優(yōu)化器使用x1索引在二級索引中查詢中一批數(shù)據(jù)A毁葱,再使用x2索引在二級索引中查詢中一批數(shù)據(jù)B,兩者做交集贰剥,再去聚簇索引中回表倾剿,這樣的效率會更高。
<p style="color:blue">多表:
<p style="color:blue">示例1:
select * from t1蚌成,t2 where t1.x1 = xxx and t1.x2 = t2.x2and t2.x3 = yyy;
第一步:查詢優(yōu)化器會根據(jù)t1.x1 = xxx這個條件查詢出一部分數(shù)據(jù)前痘,具體通過ref、index担忧、conf芹缔、all根據(jù)你索引的情況而定。
假設(shè)第一步拿出來了兩條記錄瓶盛,然后拿著這兩條記錄的x2值和x3值去t2表中去匹配有沒有一樣的最欠,有的話就關(guān)聯(lián)起來返回,其中t1叫做驅(qū)動表惩猫,t2叫做被驅(qū)動表芝硬。
<p style="color:blue">示例2:
嵌套循環(huán)查詢:簡單來說就是從驅(qū)動表中查詢一批數(shù)據(jù),然后遍歷這批數(shù)據(jù)挨個去被驅(qū)動表中查詢轧房。
這時如果被驅(qū)動表中的使用的該字段沒有加索引拌阴,每次查詢都是all,就會導(dǎo)致連表查詢速度很慢奶镶,因此最好兩者都建立索引迟赃。
<p style="color:blue">explain時你會關(guān)注哪幾個字段?
答:6個厂镇,如下
id:每一個selct語句都有有一個id纤壁,復(fù)雜的SQL有多個select,就會對應(yīng)有多個id
select_type: 當(dāng)前sql的查詢類型
type:ref捺信、index酌媒、all、const
possible_keys 可以使用的索引都會放在這里
rows:掃描的行數(shù)
table:查詢的哪張表
8残黑、說說MySQL支持的數(shù)據(jù)類型
INT(6),6即是其寬度指示器斋否,該寬度指示器并不會影響int列存儲字段的大小梨水,也就是說,超過6位它不會自動截取茵臭,依然會存儲疫诽,只有超過它本身的存儲范圍才會截取;此處寬度指示器的作用在于該字段是否有zerofill,如果有就未滿足6位的部分就會用0來填充),
CHAR 類型用于定長字符串奇徒,并且必須在圓括號內(nèi)用一個大小修飾符來定義雏亚。這個大小修飾符的范圍從 0-255。比指定長度大的值將被截短摩钙,而比指定長度小的值將會用空格作填補罢低。
CHAR 類型的一個變體是 VARCHAR 類型。它是一種可變長度的字符串類型胖笛,并且也必須帶有一個范圍指示器网持。
CHAR 和 VARCHGAR 不同之處在于 MYSQL 數(shù)據(jù)庫處理這個指示器的方式:CHAR 把這個大小視為值的大小,不長度不足的情況下就用空格補足长踊。而 VARCHAR 類型把它視為最大值并且只使用存儲字符串實際需要的長度(增加一個額外字節(jié)來存儲字符串本身的長度)來存儲值功舀。所以短于指示器長度的 VARCHAR 類型不會被空格填補,但長于指示器的值仍然會被截短身弊。
https://www.cnblogs.com/liangxiaofeng/p/5806874.html
9. 了解數(shù)據(jù)庫如何備份嗎
參考: https://www.cnblogs.com/yourblog/p/10381962.html
備份整個數(shù)據(jù)庫
$> mysqldump -u root -h host -p dbname > backdb.sql
備份數(shù)據(jù)庫中的某個表
$> mysqldump -u root -h host -p dbname tbname1辟汰, tbname2 > backdb.sql
備份多個數(shù)據(jù)庫
$> mysqldump -u root -h host -p --databases dbname1, dbname2 > backdb.sql
備份系統(tǒng)中所有數(shù)據(jù)庫
$> mysqldump -u root -h host -p --all-databases > backdb.sql
10. Oracle和Mysql的區(qū)別
<p style="color:blue">宏觀上:
Mysql是小型數(shù)據(jù)庫阱佛, 開源帖汞, 免費, Oracle收費
Oracle支持大并發(fā)瘫絮, 大訪問量
MySql中安裝后占用的內(nèi)存小涨冀, Oracle不僅占用內(nèi)存大, 而且越用越大
<p style="color:blue">微觀上:
Mysql對事務(wù)默認不支持麦萤, 但是它的存儲引擎 InnoDB支持事務(wù)鹿鳖, Oracle對事務(wù)完全支持
并發(fā)性: MySQL早期的數(shù)據(jù)引擎MyISAM是支持表級鎖, 后來的InnoDB才支持行級鎖壮莹, Oracle支持行級鎖
Oracle會將提交的sql寫入連接日志中翅帜, 然后寫入磁盤, 保證不會丟失數(shù)據(jù)命满, MySql在執(zhí)行更新的操作時可能會丟失數(shù)據(jù)
-
隔離級別不同:
a. Oracle默認使用 read commited 讀已經(jīng)提交
b. MySQL默認使用的是 repeatable read 可重復(fù)讀
-
提交方式
a. Oracle 默認不會自動提交事務(wù)
b. MySQL默認自動提交事務(wù)
-
邏輯備份
a. Mysql 的數(shù)據(jù)備份會鎖定數(shù)據(jù)涝滴, 影響正常的DML
b. Oracle在數(shù)據(jù)備份時, 不會鎖定任何數(shù)據(jù)
-
數(shù)據(jù)插入
a. Mysql會更加靈活一點胶台, 比如limit分頁歼疮, insert插入多行數(shù)據(jù)
b. Oracle的分頁使用偽列+子查詢實現(xiàn) , 插入數(shù)據(jù)也只能一行行插入
-
權(quán)限控制:
a. Oracle的權(quán)限控制是中規(guī)中矩的诈唬, 和系統(tǒng)用戶無關(guān)
b. MySQL的權(quán)限控制和主機相關(guān)韩脏, 感覺沒啥意義
-
性能診斷
a. Oracle 有大量的性能診斷工具, 可以實現(xiàn)自動分析
b. Mysql性能診斷方法很少铸磅, 主要就是通過通過慢查詢?nèi)罩救ヅ挪?/p>
-
分區(qū)表和分區(qū)索引
a. Oracle的分區(qū)表和分區(qū)索引相對來說比較成熟
b. Mysql 分區(qū)表和分區(qū)索引就不成熟
-
數(shù)據(jù)復(fù)制
a. 在搭建的主從復(fù)制的模式中赡矢, 主庫出現(xiàn)了問題杭朱, 可能會導(dǎo)致從庫有一定數(shù)據(jù)的丟失, 需要手動的切換的到主庫
b. Oracle 則更強大吹散, 既有傳統(tǒng)的推/拉式的數(shù)據(jù)復(fù)制弧械, 同時也有 dataguard雙機或者多機的容災(zāi)機制, 而且主庫出現(xiàn)問題空民, 自動切換到備庫刃唐, 但是配置相對復(fù)雜
11. 事務(wù)的四種特性
<p style="color:blue">ACID:
Atomic 原子性: 事務(wù)不能被分割, 要么都做袭景, 要么都不做唁桩。
Consistency 一致性: 可以用轉(zhuǎn)賬的例子解釋一致性。
Isolation 隔離性 : 不同的事務(wù)耸棒, 彼此隔離荒澡, 互不干擾。
Durability 持久性: 也叫做用就行与殃, 事務(wù)一旦被提交单山, 對數(shù)據(jù)庫做出的修改將被持久化 。
12. 四種隔離級別以及什么是臟讀幅疼,幻讀米奸,不可重復(fù)讀
read uncommitted 讀未提交: 在事務(wù)A中讀取到了事務(wù)B中未提交的數(shù)據(jù), 也叫做臟讀爽篷。
read commited 讀已提交: Oracle默認使用的隔離級別悴晰, 讀已提交, 說白了逐工, 事務(wù)A先開啟铡溪, 然后事務(wù)B再開啟, 然后事務(wù)Bcommit一個事務(wù)操作泪喊, 修改數(shù)據(jù) 棕硫, 那么這個修改是能被事務(wù)A讀取到的, 這就叫做讀已提交袒啼, 也是所謂的不可重復(fù)讀哈扮,(因為重復(fù)讀之后, 數(shù)據(jù)可能會發(fā)生變化)蚓再。
repeatable read : 可重復(fù)讀滑肉, 這也是Mysql默認的事務(wù)隔離級別, 事務(wù)A開啟后摘仅, 無論讀取多少次靶庙, 得到的結(jié)果都和第一次得到的結(jié)果是一樣的, 但是如果事務(wù)B在事務(wù)A第一次讀取的范圍內(nèi)插入了一條數(shù)據(jù)的話实檀, 會發(fā)生幻讀惶洲, 兩次讀取結(jié)果又不一致了, Mysql的InnoDB引擎通過多版本并發(fā)控制MVCC解決了這個問題膳犹。
serializable : 可串行化恬吕, 最高的事務(wù)隔離級別, 到是也是效率最低的事務(wù)隔離級別须床。
13. MySQL中 主鍵索引铐料、普通索引、唯一索引的區(qū)別
<p style="color:blue">主鍵索引 primary key:
一個表只能有一個主鍵索引豺旬。
主鍵索引不能為空钠惩。
主鍵索引可以做外鍵。
<p style="color:blue">唯一索引unique key:
一張表可以存在多個唯一索引族阅。
唯一索引可以是一列或者多列篓跛。
唯一索引不可重復(fù)的。
因為這個原因坦刀, 限制唯一索引做多有一個null愧沟。
<p style="color:blue">普通索引 normal key :
普通一般是為了加快數(shù)據(jù)的訪問速度而建立的。
針對那些經(jīng)常被查詢鲤遥, 或者經(jīng)常被排序的字段建立沐寺。
被索引的數(shù)據(jù)允許出現(xiàn)重復(fù)的值。
14. 數(shù)據(jù)庫三大范式
<p style="color:blue">第一大范式:
關(guān)系模式R中的所有屬性都不能再分解盖奈, 稱關(guān)系模式R 滿足第一范式混坞, 比如 address 字段就可以繼續(xù)拆分成 省市區(qū), 我們就可以認為address不滿足第一范式钢坦。
<p style="color:blue">第二大范式:
在滿足第一范式的基礎(chǔ)上更進一步究孕, 它要求所有的非主屬性都必須完全依賴于第一范式中確定下來的主屬性, 換句話說场钉, 比如聯(lián)合主鍵就不符合第二范式蚊俺, 因為很有可能這個表中的一部分非主屬性和聯(lián)合主鍵中的一部分列是有依賴關(guān)系的, 而和另外一部分并沒有依賴關(guān)系逛万。
<p style="color:blue">第三大范式:
在第一范式R的基礎(chǔ)上泳猬, 更進一步, 要求所有的字段都可主鍵直接相關(guān)而不能間接相關(guān)宇植, 比如用戶表里面不要出現(xiàn)訂單表中的訂單信息得封。
15. sql語句各種條件的執(zhí)行順序,如select指郁, where忙上, order by, group by
from where group by having order by limit select
16. 求表的size闲坎,或做數(shù)據(jù)統(tǒng)計可用什么存儲引擎
<p style="color:blue">查詢數(shù)據(jù)表所占的容量
select sum(DATA_LENGTH) + sum(INDEX_LENGTH) from information_schema.tables where table_schema = '數(shù)據(jù)庫名
<p style="color:blue">查詢所有數(shù)據(jù)的大小疫粥, 用兆的方式輸出結(jié)果
select concat(round(sum(DATA_LENGTH/1024/1024)茬斧,2),'MB') asdata
from information_schema.tables
where table_schema='blog'andtable_name='catalog'
17. 讀多寫少可用什么引擎
MyISAM 它在設(shè)計之時就考慮到 數(shù)據(jù)庫被查詢的次數(shù)要遠大于更新的次數(shù)梗逮。因此项秉,ISAM執(zhí)行讀取操作的速度很快,而且不占用大量的內(nèi)存和存儲資源慷彤。
所以娄蔼, 如果系統(tǒng)中的寫操作真的很少,并且不使用mysql的事務(wù)等高級操作的話底哗, 建議使用MYISAM岁诉。
18. 假如要統(tǒng)計多個表應(yīng)該用什么引擎
考慮報表引擎
19.MySQL Explain各字段意思
字段名 | 含義 |
---|---|
id | 選擇標識符 |
select_type | 表示查詢的類型 |
table | 輸出結(jié)果集的表 |
partitions | 匹配的分區(qū) |
type | 表示表的連接類型 |
possible_keys | 表示查詢時,可能使用的索引 |
key | 表示實際使用的索引 |
key_len | 索引字段的長度 |
ref | 列與索引的比較 |
rows | 掃描出的行數(shù)(估算的行數(shù)) |
filtered | 按表條件過濾的行百分比 |
Extra | 執(zhí)行情況的描述和說明 |
20.索引設(shè)計的原則跋选?
適合索引的列是出現(xiàn)在where子句中的列涕癣,或者連接子句中指定的列。
基數(shù)較小的類前标,索引效果較差属划,沒有必要在此列建立索引。
使用短索引候生,如果對長字符串列進行索引同眯,應(yīng)該指定一個前綴長度,這樣能夠節(jié)省大量索引空間唯鸭。
不要過度索引须蜗。索引需要額外的磁盤空間,并降低寫操作的性能目溉。在修改表內(nèi)容的時候明肮,索引會進行更新甚至重構(gòu),索引列越多缭付,這個時間就會越長柿估。所以只保持需要的索引有利于查詢即可。
21. MySQL有關(guān)權(quán)限的表有哪幾個陷猫?
表名 | 含義 |
---|---|
user權(quán)限表 | 記錄允許連接到服務(wù)器的用戶帳號信息秫舌,里面的權(quán)限是全局級的。 |
db權(quán)限表 | 記錄各個帳號在各個數(shù)據(jù)庫上的操作權(quán)限绣檬。 |
table_priv權(quán)限表 | 記錄數(shù)據(jù)表級的操作權(quán)限足陨。 |
columns_priv權(quán)限表 | 記錄數(shù)據(jù)列級的操作權(quán)限。 |
host權(quán)限表 | 配合db權(quán)限表對給定主機上數(shù)據(jù)庫級操作權(quán)限作更細致的控制娇未。這個權(quán)限表不受GRANT和REVOKE語句的影響墨缘。 |
二、白日夢的MySQL專題
2宽涌、聊聊什么是慢查?如何監(jiān)控蝶棋?如何排查护糖?
3、對Not Null字段插入Null值有啥現(xiàn)象嚼松?
4、能談?wù)剏ear锰扶、date献酗、datetime、time坷牛、timestamp的區(qū)別嗎罕偎?
5、你有沒有搞混查詢緩存和Buffer Pool京闰?談?wù)効矗?/a>
6颜及、你知道數(shù)據(jù)庫緩沖池中的LRU-List嗎?
7蹂楣、了解InnoDB的FreeList嗎俏站?談?wù)効矗?/a>
8、了解Flush-List嗎痊土?順便說一下臟頁的落盤機制肄扎!
9、用 11 張圖講清楚赁酝,當(dāng)你CRUD時BufferPool中發(fā)生了什么犯祠!以及BufferPool的優(yōu)化!
10酌呆、了解 MySQL的表空間 和 數(shù)據(jù)表嗎衡载?談?wù)効矗?/a>
11、了解 MySQL的數(shù)據(jù)行嗎隙袁?行溢出機制呢痰娱?談?wù)効矗?/a>
12、了解MySQL數(shù)據(jù)頁嗎菩收?說說什么是頁分裂吧猜揪!
13、用一分鐘了解fsync這個系統(tǒng)調(diào)用
14坛梁、簡述undo log而姐、truncate、以及undo log如何幫你回滾事務(wù)划咐?
16风瘦、傳說中的MySQL的redo log是什么?談?wù)効矗?/a>
17公般、LSN万搔、Checkpoint?談?wù)凪YSQL的崩潰恢復(fù)是怎么回事官帘!
18瞬雹、MySQL的 bin log有啥用?在哪里刽虹?誰寫的酗捌?怎么配置?
19涌哲、bin log有哪些格式胖缤?有啥區(qū)別?優(yōu)缺點阀圾?線上用哪種格式哪廓?
20、MySQL的修仙之路初烘,圖文談?wù)勅绾螌W(xué)MySQL撩独、如何進階!
<p style="color:red"> 文章公眾號首發(fā)账月,連載中综膀,歡迎關(guān)注白日夢,一起沖鴨局齿!
<p style="color:red"> 文章公眾號首發(fā)剧劝,連載中,歡迎關(guān)注白日夢抓歼,一起沖鴨讥此!
<p style="color:red"> 文章公眾號首發(fā),連載中谣妻,歡迎關(guān)注白日夢萄喳,一起沖鴨!
三蹋半、Redis問答
1. redis能存哪些類型
string == Map<String他巨,String>
map == Map<String,Map<String>>
list == Map<String , List<String>>
set == Map<String染突,Set<String>>
zset == Map<String捻爷,ZSet<String>>
2、redis為什么這么快份企? 高并發(fā)如何處理的也榄?
<p style="color:blue">高并發(fā)的原因:
1.redis是基于內(nèi)存的,內(nèi)存的讀寫速度非乘局荆快甜紫;
2.redis是單線程的,省去了很多上下文切換線程的時間骂远;
3.redis使用多路復(fù)用技術(shù)囚霸,可以處理并發(fā)的連接。非阻塞IO 內(nèi)部實現(xiàn)采用epoll吧史,采用了epoll+自己實現(xiàn)的簡單的事件框架。epoll中的讀唠雕、寫贸营、關(guān)閉、連接都轉(zhuǎn)化成了事件岩睁,然后利用epoll的多路復(fù)用特性钞脂,絕不在io上浪費一點時間。
<p style="color:blue">為什么Redis是單線程的:
官方答案: 因為Redis是基于內(nèi)存的操作捕儒,CPU不是Redis的瓶頸冰啃,Redis的瓶頸最有可能是機器內(nèi)存的大小或者網(wǎng)絡(luò)帶寬。既然單線程容易實現(xiàn)刘莹,而且CPU不會成為瓶頸阎毅,那就順理成章地采用單線程的方案了。
不需要各種鎖的性能消耗
Redis的數(shù)據(jù)結(jié)構(gòu)并不全是簡單的Key-Value点弯,還有l(wèi)ist扇调,hash等復(fù)雜的結(jié)構(gòu),這些結(jié)構(gòu)有可能會進行很細粒度的操作抢肛,比如在很長的列表后面添加一個元素狼钮,在hash當(dāng)中添加或者刪除
一個對象。這些操作可能就需要加非常多的鎖捡絮,導(dǎo)致的結(jié)果是同步開銷大大增加熬芜。
總之,在單線程的情況下福稳,就不用去考慮各種鎖的問題涎拉,不存在加鎖釋放鎖操作,沒有因為可能出現(xiàn)死鎖而導(dǎo)致的性能消耗。
<p style="color:blue">CPU消耗:
采用單線程曼库,避免了不必要的上下文切換和競爭條件区岗,也不存在多進程或者多線程導(dǎo)致的切換而消耗 CPU。
但是如果CPU成為Redis瓶頸毁枯,或者不想讓服務(wù)器其他CUP核閑置慈缔,那怎么辦?
可以考慮多起幾個Redis進程种玛,Redis是key-value數(shù)據(jù)庫藐鹤,不是關(guān)系數(shù)據(jù)庫,數(shù)據(jù)之間沒有約束赂韵。只要客戶端分清哪些key放在哪個Redis進程上就可以了娱节。
3.過期鍵的刪除策略
我們都知道,Redis是key-value數(shù)據(jù)庫祭示,我們可以設(shè)置Redis中緩存的key的過期時間肄满。Redis的過期策略就是指當(dāng)Redis中緩存的key過期了,Redis如何處理质涛。
<p style="color:blue">過期策略通常有以下三種:
- 定時過期:每個設(shè)置過期時間的key都需要創(chuàng)建一個定時器稠歉,到過期時間就會立即清除。該策略可以立即清除過期的數(shù)據(jù)汇陆,對內(nèi)存很友好怒炸;但是會占用大量的CPU資源去處理過期的數(shù)據(jù),從而影響緩存的響應(yīng)時間和吞吐量毡代。
- 惰性過期:只有當(dāng)訪問一個key時阅羹,才會判斷該key是否已過期,過期則清除教寂。該策略可以最大化地節(jié)省CPU資源捏鱼,卻對內(nèi)存非常不友好。極端情況可能出現(xiàn)大量的過期key沒有再次被訪問酪耕,從而不會被清除穷躁,占用大量內(nèi)存。
- 定期過期:每隔一定的時間因妇,會掃描一定數(shù)量的數(shù)據(jù)庫的expires字典中一定數(shù)量的key问潭,并清除其中已過期的key。該策略是前兩者的一個折中方案婚被。通過調(diào)整定時掃描的時間間隔和每次掃描的限定耗時狡忙,可以在不同情況下使得CPU和內(nèi)存資源達到最優(yōu)的平衡效果。
(expires字典會保存所有設(shè)置了過期時間的key的過期時間數(shù)據(jù)址芯,其中灾茁,key是指向鍵空間中的某個鍵的指針窜觉,value是該鍵的毫秒精度的UNIX時間戳表示的過期時間。鍵空間是指該Redis集群中保存的所有鍵北专。)
Redis中同時使用了惰性過期和定期過期兩種過期策略禀挫。
4.Redis的內(nèi)存淘汰策略有哪些
Redis的內(nèi)存淘汰策略是指在Redis的用于緩存的內(nèi)存不足時,怎么處理需要新寫入且需要申請額外空間的數(shù)據(jù)拓颓。
全局的鍵空間選擇性移除
noeviction:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時语婴,新寫入操作會報錯。
allkeys-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時驶睦,在鍵空間中砰左,移除最近最少使用的key。(這個是最常用的)
allkeys-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時场航,在鍵空間中缠导,隨機移除某個key。
設(shè)置過期時間的鍵空間選擇性移除
volatile-lru:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時溉痢,在設(shè)置了過期時間的鍵空間中僻造,移除最近最少使用的key。
volatile-random:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時孩饼,在設(shè)置了過期時間的鍵空間中髓削,隨機移除某個key。
volatile-ttl:當(dāng)內(nèi)存不足以容納新寫入數(shù)據(jù)時捣辆,在設(shè)置了過期時間的鍵空間中蔬螟,有更早過期時間的key優(yōu)先移除此迅。
5. RedLock
Redis 官方站提出了一種權(quán)威的基于 Redis 實現(xiàn)分布式鎖的方式名叫 Redlock汽畴,此種方式比原先的單節(jié)點的方法更安全。它可以保證以下特性:
安全特性:互斥訪問耸序,即永遠只有一個 client 能拿到鎖忍些。
避免死鎖:最終 client 都可能拿到鎖,不會出現(xiàn)死鎖的情況坎怪,即使原本鎖住某資源的 client crash 了或者出現(xiàn)了網(wǎng)絡(luò)分區(qū)罢坝。
容錯性:只要大部分 Redis 節(jié)點存活就可以正常提供服務(wù)。
6. Redis緩存異常--緩存雪崩
緩存雪崩是指緩存同一時間大面積的失效搅窿,所以嘁酿,后面的請求都會落到數(shù)據(jù)庫上,造成數(shù)據(jù)庫短時間內(nèi)承受大量請求而崩掉男应。
解決方案
緩存數(shù)據(jù)的過期時間設(shè)置隨機闹司,防止同一時間大量數(shù)據(jù)過期現(xiàn)象發(fā)生。
一般并發(fā)量不是特別多的時候沐飘,使用最多的解決方案是加鎖排隊游桩。
給每一個緩存數(shù)據(jù)增加相應(yīng)的緩存標記牲迫,記錄緩存的是否失效,如果緩存標記失效借卧,則更新數(shù)據(jù)緩存盹憎。
7. Redis緩存異常--緩存穿透
緩存穿透是指緩存和數(shù)據(jù)庫中都沒有的數(shù)據(jù),導(dǎo)致所有的請求都落到數(shù)據(jù)庫上铐刘,造成數(shù)據(jù)庫短時間內(nèi)承受大量請求而崩掉陪每。
<p style="color:blue">解決方案
接口層增加校驗械筛,如用戶鑒權(quán)校驗伞梯,id做基礎(chǔ)校驗,id<=0的直接攔截盒犹;
從緩存取不到的數(shù)據(jù)捡遍,在數(shù)據(jù)庫中也沒有取到锌订,這時也可以將key-value對寫為key-null,緩存有效時間可以設(shè)置短點画株,如30秒(設(shè)置太長會導(dǎo)致正常情況也沒法使用)辆飘。這樣可以防止攻擊用戶反復(fù)用同一個id暴力攻擊
采用布隆過濾器,將所有可能存在的數(shù)據(jù)哈希到一個足夠大的 bitmap 中谓传,一個一定不存在的數(shù)據(jù)會被這個 bitmap 攔截掉蜈项,從而避免了對底層存儲系統(tǒng)的查詢壓力
<p style="color:blue">附加
對于空間的利用到達了一種極致,那就是Bitmap和布隆過濾器(Bloom Filter)续挟。
Bitmap: 典型的就是哈希表
缺點是:Bitmap對于每個元素只能記錄1bit信息紧卒,如果還想完成額外的功能,恐怕只能靠犧牲更多的空間诗祸、時間來完成了跑芳。
布隆過濾器(推薦)
就是引入了k(k>1)k(k>1)
個相互獨立的哈希函數(shù),保證在給定的空間直颅、誤判率下博个,完成元素判重的過程。
它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法功偿,缺點是有一定的誤識別率和刪除困難盆佣。
Bloom-Filter算法的核心思想就是利用多個不同的Hash函數(shù)來解決“沖突”。
Hash存在一個沖突(碰撞)的問題械荷,用同一個Hash得到的兩個URL的值有可能相同共耍。為了減少沖突,我們可以多引入幾個Hash吨瞎,如果通過其中的一個Hash值我們得出某元素不在集合中痹兜,那么該元素肯定不在集合中。只有在所有的Hash函數(shù)告訴我們該元素在集合中時关拒,才能確定該元素存在于集合中佃蚜。這便是Bloom-Filter的基本思想庸娱。
Bloom-Filter一般用于在大數(shù)據(jù)量的集合中判定某元素是否存在。
8. Redis緩存異常--緩存擊穿
緩存擊穿是指緩存中沒有但數(shù)據(jù)庫中有的數(shù)據(jù)(一般是緩存時間到期)谐算,這時由于并發(fā)用戶特別多熟尉,同時讀緩存沒讀到數(shù)據(jù),又同時去數(shù)據(jù)庫去取數(shù)據(jù)洲脂,引起數(shù)據(jù)庫壓力瞬間增大斤儿,造成過大壓力。和緩存雪崩不同的是恐锦,緩存擊穿指并發(fā)查同一條數(shù)據(jù)往果,緩存雪崩是不同數(shù)據(jù)都過期了,很多數(shù)據(jù)都查不到從而查數(shù)據(jù)庫一铅。
<p style="color:blue">解決方案
設(shè)置熱點數(shù)據(jù)永遠不過期陕贮。
加互斥鎖,互斥鎖潘飘。
9. 緩存預(yù)熱
緩存預(yù)熱就是系統(tǒng)上線后肮之,將相關(guān)的緩存數(shù)據(jù)直接加載到緩存系統(tǒng)。這樣就可以避免在用戶請求的時候卜录,先查詢數(shù)據(jù)庫戈擒,然后再將數(shù)據(jù)緩存的問題!用戶直接查詢事先被預(yù)熱的緩存數(shù)據(jù)艰毒!
<p style="color:blue">解決方案
直接寫個緩存刷新頁面筐高,上線時手工操作一下;
數(shù)據(jù)量不大丑瞧,可以在項目啟動的時候自動進行加載柑土;
定時刷新緩存;
10.如何保證數(shù)據(jù)庫和緩存雙寫一致性
你只要用緩存嗦篱,就可能會涉及到緩存與數(shù)據(jù)庫雙存儲雙寫冰单,你只要是雙寫幌缝,就一定會有數(shù)據(jù)一致性的問題灸促,那么你如何解決一致性問題?
一般來說涵卵,就是如果你的系統(tǒng)不是嚴格要求緩存+數(shù)據(jù)庫必須一致性的話浴栽,緩存可以稍微的跟數(shù)據(jù)庫偶爾有不一致的情況,最好不要做這個方案轿偎,讀請求和寫請求串行化典鸡,串到一個內(nèi)存隊列里去,這樣就可以保證一定不會出現(xiàn)不一致的情況坏晦。
串行化之后萝玷,就會導(dǎo)致系統(tǒng)的吞吐量會大幅度的降低嫁乘,用比正常情況下多幾倍的機器去支撐線上的一個請求。
還有一種方式就是可能會暫時產(chǎn)生不一致的情況球碉,但是發(fā)生的幾率特別小蜓斧,就是先更新數(shù)據(jù)庫,然后再刪除緩存睁冬。
問題場景 | 描述 | 解決 |
---|---|---|
先寫緩存挎春,再寫數(shù)據(jù)庫,緩存寫成功豆拨,數(shù)據(jù)庫寫失敗 | 緩存寫成功直奋,但寫數(shù)據(jù)庫失敗或者響應(yīng)延遲,則下次讀仁┖獭(并發(fā)讀)緩存時脚线,就出現(xiàn)臟讀 | 這個寫緩存的方式,本身就是錯誤的弥搞,需要改為先寫數(shù)據(jù)庫殉挽,把舊緩存置為失效;讀取數(shù)據(jù)的時候拓巧,如果緩存不存在斯碌,則讀取數(shù)據(jù)庫再寫緩存 |
先寫數(shù)據(jù)庫,再寫緩存肛度,數(shù)據(jù)庫寫成功傻唾,緩存寫失敗 | 寫數(shù)據(jù)庫成功,但寫緩存失敗承耿,則下次讀裙诮尽(并發(fā)讀)緩存時,則讀不到數(shù)據(jù) | 緩存使用時加袋,假如讀緩存失敗凛辣,先讀數(shù)據(jù)庫,再回寫緩存的方式實現(xiàn) |
需要緩存異步刷新 | 指數(shù)據(jù)庫操作和寫緩存不在一個操作步驟中职烧,比如在分布式場景下扁誓,無法做到同時寫緩存或需要異步刷新(補救措施)時候 | 確定哪些數(shù)據(jù)適合此類場景,根據(jù)經(jīng)驗值確定合理的數(shù)據(jù)不一致時間蚀之,用戶數(shù)據(jù)刷新的時間間隔 |
11.假如Redis里面有1億個key蝗敢,其中有10w個key是以某個固定的已知的前綴開頭的,如果將它們?nèi)空页鰜恚?/h4>
使用keys指令可以掃出指定模式的key列表足删。
對方接著追問:如果這個redis正在給線上的業(yè)務(wù)提供服務(wù)寿谴,那使用keys指令會有什么問題?
這個時候你要回答redis關(guān)鍵的一個特性:redis的單線程的失受。keys指令會導(dǎo)致線程阻塞一段時間讶泰,線上服務(wù)會停頓咏瑟,直到指令執(zhí)行完畢,服務(wù)才能恢復(fù)痪署。這個時候可以使用scan指令响蕴,scan指令可以無阻塞的提取出指定模式的key列表,但是會有一定的重復(fù)概率惠桃,在客戶端做一次去重就可以了浦夷,但是整體所花費的時間會比直接用keys指令長。