關(guān)系型數(shù)據(jù)庫(kù)和非關(guān)系型數(shù)據(jù)庫(kù)的區(qū)別
在關(guān)系型數(shù)據(jù)庫(kù)中,數(shù)據(jù)存儲(chǔ)于一張張固定行列的表中;而非關(guān)系型數(shù)據(jù)庫(kù)中,數(shù)據(jù)有文檔、鍵值對(duì)、圖、寬列等多種存儲(chǔ)方式。
MySQL數(shù)據(jù)庫(kù)
MyISAM和InnoDB存儲(chǔ)引擎的區(qū)別
- MyISAM只能支持表級(jí)鎖,InnoDB可以支持行級(jí)鎖和MVCC;
- MyISAM不支持事務(wù),InnoDB支持事務(wù);
- MyISAM不支持?jǐn)?shù)據(jù)庫(kù)異常崩潰后安全恢復(fù),InnoDB支持;
- 索引實(shí)現(xiàn)不一樣;
- InnoDB在多核情況下讀寫能力呈線性增長(zhǎng);
- InnoDB支持外鍵(感覺無(wú)關(guān)緊要,畢竟現(xiàn)在盡量不用外鍵了)
事務(wù)
事務(wù)是邏輯上的一組操作,要么都執(zhí)行,要么都不執(zhí)行
用事務(wù)的原子性,隔離性和持久性來(lái)保證數(shù)據(jù)的一致性。
并發(fā)事務(wù)帶來(lái)的問(wèn)題
- 臟讀
- 丟失更改
- 不可重復(fù)讀
- 幻讀
并發(fā)事務(wù)的控制方式
通過(guò)鎖或者MVCC來(lái)避免并發(fā)事務(wù)帶來(lái)的問(wèn)題。
鎖
- 共享鎖:讀鎖,事務(wù)在讀取記錄的時(shí)候獲取共享鎖,允許多個(gè)事務(wù)讀取時(shí)也獲??;
- 排他鎖:寫鎖/獨(dú)占鎖。
MVCC(多版本并發(fā)控制方法)
對(duì)一份數(shù)據(jù)會(huì)存儲(chǔ)多個(gè)版本,通過(guò)事務(wù)的可見性來(lái)保證事務(wù)能看到自己應(yīng)該看到的版本。
MVCC 在 MySQL 中實(shí)現(xiàn)所依賴的手段主要是: 隱藏字段、read view、undo log。
事務(wù)隔離級(jí)別
- 讀取未提交
- 讀取已提交
- 可重復(fù)讀
- 可串行化
索引
常見索引列建議
- 出現(xiàn)在 SELECT、UPDATE、DELETE 語(yǔ)句的 WHERE 從句中的列
- 包含在 ORDER BY、GROUP BY、DISTINCT 中的字段
- 不要將符合 1 和 2 中的字段的列都建立一個(gè)索引, 通常將 1、2 中的字段建立聯(lián)合索引效果更好
- 多表 join 的關(guān)聯(lián)列
如何選擇索引列的順序
- 區(qū)分度高的放到聯(lián)合索引的最左側(cè)
- 字段長(zhǎng)度小的放到聯(lián)合索引的最左側(cè)
- 使用最頻繁的列放到聯(lián)合索引最左側(cè)
索引的優(yōu)缺點(diǎn)
優(yōu)點(diǎn):在數(shù)據(jù)量大的情況下,索引能提高查詢速度;通過(guò)創(chuàng)建唯一性索引,可以保證數(shù)據(jù)庫(kù)表中每一行數(shù)據(jù)的唯一性
缺點(diǎn):創(chuàng)建索引需要耗費(fèi)時(shí)間,影響插入效率;索引也是數(shù)據(jù)文件,占用存儲(chǔ)空間
索引結(jié)構(gòu)
在InnoDB中,主索引的鍵是主鍵,葉子節(jié)點(diǎn)的數(shù)據(jù)就是該條記錄,其他索引葉子節(jié)點(diǎn)的數(shù)據(jù)是主鍵值。因此,使用輔助索引查到的只是主鍵值,還要再走一遍主索引才能拿到數(shù)據(jù)。
MyISAM 引擎中,B+Tree 葉節(jié)點(diǎn)的 data 域存放的是數(shù)據(jù)記錄的地址。在索引檢索的時(shí)候,首先按照 B+Tree 搜索算法搜索索引,如果指定的 Key 存在,則取出其 data 域的值,然后以 data 域的值為地址讀取相應(yīng)的數(shù)據(jù)記錄。這被稱為“非聚簇索引(非聚集索引)”。
InnoDB 引擎中,其數(shù)據(jù)文件本身就是索引文件。相比 MyISAM,索引文件和數(shù)據(jù)文件是分離的,其表數(shù)據(jù)文件本身就是按 B+Tree 組織的一個(gè)索引結(jié)構(gòu),樹的葉節(jié)點(diǎn) data 域保存了完整的數(shù)據(jù)記錄。這個(gè)索引的 key 是數(shù)據(jù)表的主鍵,因此 InnoDB 表數(shù)據(jù)文件本身就是主索引。這被稱為“聚簇索引(聚集索引)”,而其余的索引都作為 輔助索引 ,輔助索引的 data 域存儲(chǔ)相應(yīng)記錄主鍵的值而不是地址,這也是和 MyISAM 不同的地方。在根據(jù)主索引搜索時(shí),直接找到 key 所在的節(jié)點(diǎn)即可取出數(shù)據(jù);在根據(jù)輔助索引查找時(shí),則需要先取出主鍵的值,再走一遍主索引。 因此,在設(shè)計(jì)表的時(shí)候,不建議使用過(guò)長(zhǎng)的字段作為主鍵,也不建議使用非單調(diào)的字段作為主鍵,這樣會(huì)造成主索引頻繁分裂。
聯(lián)合索引和覆蓋索引的區(qū)別
使用表中的多個(gè)字段創(chuàng)建索引,就是 聯(lián)合索引,也叫 組合索引 或 復(fù)合索引。
覆蓋索引即需要查詢的字段正好是索引的字段,那么直接根據(jù)該索引,就可以查到數(shù)據(jù)了,而無(wú)需回表查詢。
聚簇索引
索引和數(shù)據(jù)放在一起的就是聚簇索引,優(yōu)點(diǎn)是無(wú)需回表查詢。
索引失效
- 使用
SELECT *進(jìn)行查詢; - 創(chuàng)建了組合索引,但查詢條件未準(zhǔn)守最左匹配原則;
- 在索引列上進(jìn)行計(jì)算、函數(shù)、類型轉(zhuǎn)換等操作;
- 以
%開頭的 LIKE 查詢比如like '%abc'; - 查詢條件中使用 or,且 or 的前后條件中有一個(gè)列沒有索引,涉及的索引都不會(huì)被使用到;
- 發(fā)生隱式轉(zhuǎn)換
MySQL日志
二進(jìn)制日志 binlog(歸檔日志),事務(wù)日志 redo log(重做日志)和 undo log(回滾日志)
redo log(重做日志)
redo log(重做日志)是InnoDB存儲(chǔ)引擎獨(dú)有的,它讓MySQL擁有了崩潰恢復(fù)能力。
比如 MySQL 實(shí)例掛了或宕機(jī)了,重啟時(shí),InnoDB存儲(chǔ)引擎會(huì)使用redo log恢復(fù)數(shù)據(jù),保證數(shù)據(jù)的持久性與完整性。
執(zhí)行時(shí)機(jī)
每次更新數(shù)據(jù)時(shí)都將更新信息記錄到重做日志緩存中,然后當(dāng)事務(wù)提交后,使用默認(rèn)策略將緩存寫到硬盤中的重做日志中。
存儲(chǔ)形式
硬盤上存儲(chǔ)的 redo log 日志文件不只一個(gè),而是以一個(gè)日志文件組的形式出現(xiàn)的,每個(gè)的redo日志文件大小都是一樣的。比如可以配置為一組4個(gè)文件,每個(gè)文件的大小是 1GB,整個(gè) redo log 日志文件組可以記錄4G的內(nèi)容。
它采用的是環(huán)形數(shù)組形式,從頭開始寫,寫到末尾又回到頭循環(huán)寫,
bin log(歸檔日志)
邏輯日志,記錄語(yǔ)句的原始邏輯,用來(lái)數(shù)據(jù)備份,主從復(fù)制等。
記錄格式
- statement: 記錄的內(nèi)容是SQL語(yǔ)句原文
- row: 記錄的內(nèi)容不再是簡(jiǎn)單的SQL語(yǔ)句了,還包含操作的具體數(shù)據(jù)。為了解決語(yǔ)句中包含now()之類語(yǔ)句而產(chǎn)生的數(shù)據(jù)不一致。
- mixed 混合形式,僅在需要實(shí)時(shí)計(jì)算的地方采用row。
執(zhí)行時(shí)機(jī)
- 事務(wù)執(zhí)行過(guò)程中,先把日志不斷寫到binlog cache,事務(wù)提交的時(shí)候,再把binlog cache合并后寫到binlog文件中。
- 二進(jìn)制日志僅在事務(wù)提交時(shí)記錄,并且對(duì)于每一個(gè)事務(wù),僅包含對(duì)應(yīng)事務(wù)的一個(gè)日志
- 重做日志其記錄的物理操作日志,因此每個(gè)事務(wù)對(duì)應(yīng)多個(gè)日志條目,并且事務(wù)的重做日志寫入是并發(fā)的,并非在事務(wù)提交時(shí)寫入,故其在文件中記錄的順序并非是事務(wù)開始的順序(下圖中帶有*的,意為該事務(wù)的提交)
兩階段提交
在事務(wù)執(zhí)行過(guò)程中記錄的redo log不會(huì)直接提交,而是進(jìn)入prepare預(yù)備階段,等事務(wù)執(zhí)行完畢且bin log寫入后,再將redo log轉(zhuǎn)為commit階段。
undo log(回滾日志)
- 當(dāng)事務(wù)回滾時(shí)用于將數(shù)據(jù)恢復(fù)到修改前的樣子
- 另一個(gè)作用是 MVCC ,當(dāng)讀取記錄時(shí),若該記錄被其他事務(wù)占用或當(dāng)前版本對(duì)該事務(wù)不可見,則可以通過(guò) undo log 讀取之前的版本數(shù)據(jù),以此實(shí)現(xiàn)非鎖定讀
總結(jié)
MySQL InnoDB 引擎使用 redo log(重做日志) 保證事務(wù)的持久性,使用 undo log(回滾日志) 來(lái)保證事務(wù)的原子性。MySQL數(shù)據(jù)庫(kù)的數(shù)據(jù)備份、主備、主主、主從都離不開binlog,需要依靠binlog來(lái)同步數(shù)據(jù),保證數(shù)據(jù)一致性。