| 作者:yandeng,騰訊 PCG 應(yīng)用開發(fā)工程師 1.數(shù)據(jù)庫基礎(chǔ)1.1 MySQL 架構(gòu)和其它數(shù)據(jù)庫相比,MySQL 有點與眾不同,它的架構(gòu)可以在多種不同場景中應(yīng)用并發(fā)揮良好作用。主要體現(xiàn)在存儲引擎的架構(gòu)上,插件式的存儲引擎架構(gòu)將查詢處理和其它的系統(tǒng)任務(wù)以及數(shù)據(jù)的存儲提取相分離。這種架構(gòu)可以根據(jù)業(yè)務(wù)的需求和實際需要選擇合適的存儲引擎,各層介紹: 1.1.1 連接層最上層是一些客戶端和連接服務(wù),包含本地 sock 通信和大多數(shù)基于客戶端/服務(wù)端工具實現(xiàn)的類似于 tcp/ip 的通信。主要完成一些類似于連接處理、授權(quán)認證、及相關(guān)的安全方案。在該層上引入了線程池的概念,為通過認證安全接入的客戶端提供線程。同樣在該層上可以實現(xiàn)基于 SSL 的安全鏈接。服務(wù)器也會為安全接入的每個客戶端驗證它所具有的操作權(quán)限。 1.1.2 服務(wù)層1.1.3 引擎層存儲引擎層,存儲引擎真正的負責(zé)了 MySQL 中數(shù)據(jù)的存儲和提取,服務(wù)器通過 API 與存儲引擎進行通信。不同的存儲引擎具有的功能不同,這樣我們可以根據(jù)自己的實際需要進行選取。 1.1.4 存儲層數(shù)據(jù)存儲層,主要是將數(shù)據(jù)存儲在運行于裸設(shè)備的文件系統(tǒng)之上,并完成與存儲引擎的交互。 1.2 數(shù)據(jù)引擎不同的存儲引擎都有各自的特點,以適應(yīng)不同的需求,如表所示。為了做出選擇,首先要考慮每一個存儲引擎提供了哪些不同的功能。 1.2.1 MyISAM使用這個存儲引擎,每個 MyISAM 在磁盤上存儲成三個文件。 
 1.2.2 InnoDBInnoDB 是默認的數(shù)據(jù)庫存儲引擎,他的主要特點有: 
 1.2.3 Memory將數(shù)據(jù)存在內(nèi)存,為了提高數(shù)據(jù)的訪問速度,每一個表實際上和一個磁盤文件關(guān)聯(lián)。文件是 frm。 
 1.3 表與字段設(shè)計1.3.1 數(shù)據(jù)庫基本設(shè)計規(guī)范
 1.3.2 數(shù)據(jù)庫字段設(shè)計規(guī)范
 1.3.3 索引設(shè)計規(guī)范
 1.3.4 數(shù)據(jù)庫 SQL 開發(fā)規(guī)范
 1.4 范式與反范式1.4.1 第一范式該范式是為了排除 重復(fù)組 的出現(xiàn),因此要求數(shù)據(jù)庫的每個列的值域都由原子值組成;每個字段的值都只能是單一值。1971 年埃德加·科德提出了第一范式。即表中所有字段都是不可再分的。解決方案:想要消除重復(fù)組的話,只要把每筆記錄都轉(zhuǎn)化為單一記錄即可。 1.4.2 第二范式表中必須存在業(yè)務(wù)主鍵,并且非主鍵依賴于全部業(yè)務(wù)主鍵。解決方案:拆分將依賴的字段單獨成表。 1.4.3 第三范式表中的非主鍵列之間不能相互依賴,將不與 PK 形成依賴關(guān)系的字段直接提出單獨成表即可。 1.5 sql 索引
 1.6 join 連表1.6.1 JOIN 按照功能大致分為如下三類:
 1.6.2 join 的原理MySQL 使用了嵌套循環(huán)(Nested-Loop Join)的實現(xiàn)方式。Nested-Loop Join 需要區(qū)分驅(qū)動表和被驅(qū)動表,先訪問驅(qū)動表,篩選出結(jié)果集,然后將這個結(jié)果集作為循環(huán)的基礎(chǔ),訪問被驅(qū)動表過濾出需要的數(shù)據(jù)。Nested-Loop Join 分下面幾種類型: 
 
 相關(guān)圖片來源于網(wǎng)絡(luò) 
 這個 buffer 被稱為 join buffer,顧名思義,就是用來緩存 join 需要的字段。MySQL 默認 buffer 大小 256K,如果有 n 個 join 操作,會生成 n-1 個 join buffer。 1.6.3 join 的優(yōu)化
  
 2.數(shù)據(jù)進階2.1 sql 執(zhí)行過程 如上圖所示,當向 MySQL 發(fā)送一個請求的時候,MySQL 到底做了什么: 
 MySQL 的查詢優(yōu)化器使用很多策略來生成一個最優(yōu)的執(zhí)行計劃。優(yōu)化策略可以簡單的分為兩種: 
 
 使用 show status like 'Last_query_cost’ 可以查詢上次執(zhí)行的語句的成本,單位為數(shù)據(jù)頁。   2.2 sql 查詢計劃使用 explain 進行執(zhí)行計劃分析:    2.3 sql 索引優(yōu)化遵循索引原則適合大部分的常規(guī)數(shù)據(jù)庫查詢場景,但不是所有的索引都能符合預(yù)期,從索引原理本身來分析對索引的創(chuàng)建會更有幫助。 
 2.3.1 前綴索引當要索引的列字符很多時 索引則會很大且變慢( 可以只索引列開始的部分字符串 節(jié)約索引空間 從而提高索引效率 ) 例如:一個數(shù)據(jù)表的 x_name 值都是類似 23213223.434323.4543.4543.34324 這種值,如果以整個字段值做索引,會使索引文件過大,但是如果設(shè)置前 7 位來做索引則不會出現(xiàn)重復(fù)索引值的情況了。  查詢效率會大大提升:  2.3.2 聯(lián)合索引順序
 使用選擇基數(shù)更高(不重復(fù)的數(shù)據(jù))的字段作為最左索引:  2.3.3 聯(lián)合索引左前綴匹配 
 2.4 慢查詢分析2.4.1 先對 sql 語句進行 explain,查看語句存在的問題2.4.2 使用 show profile 查看執(zhí)行耗時,分析具體耗時原因show profile 的使用指引:  2.5 改表與 sql 日志2.5.1 改表改表會直接觸發(fā)表鎖,改表過程非常耗時,對于大表修改,無論是字段類型調(diào)整還是字段增刪,都需要謹慎操作,防止業(yè)務(wù)表操作被阻塞,大表修改往往有以下幾種方式。 
 常用方法:  2.5.2 sql 日志  2.6 分庫與分表2.6.1 數(shù)據(jù)庫瓶頸不管是 IO 瓶頸,還是 CPU 瓶頸,最終都會導(dǎo)致數(shù)據(jù)庫的活躍連接數(shù)增加,進而逼近甚至達到數(shù)據(jù)庫可承載活躍連接數(shù)的閾值。在業(yè)務(wù) Service 來看就是,可用數(shù)據(jù)庫連接少甚至無連接可用。接下來就可以想象了吧(并發(fā)量、吞吐量、崩潰)。 
 第二種:網(wǎng)絡(luò) IO 瓶頸,請求的數(shù)據(jù)太多,網(wǎng)絡(luò)帶寬不夠 -> 分庫。 
 第二種:單表數(shù)據(jù)量太大,查詢時掃描的行太多,SQL 效率低,CPU 率先出現(xiàn)瓶頸 -> 水平分表。 2.6.2 分庫分表
 概念:以字段為依據(jù),按照一定策略(hash、range 等),將一個庫中的數(shù)據(jù)拆分到多個庫中。結(jié)果:每個庫的結(jié)構(gòu)都一樣;每個庫的數(shù)據(jù)都不一樣,沒有交集;所有庫的并集是全量數(shù)據(jù);場景:系統(tǒng)絕對并發(fā)量上來了,分表難以根本上解決問題,并且還沒有明顯的業(yè)務(wù)歸屬來垂直分庫。分析:庫多了,io 和 cpu 的壓力自然可以成倍緩解。 
 概念:以字段為依據(jù),按照一定策略(hash、range 等),將一個表中的數(shù)據(jù)拆分到多個表中。結(jié)果:每個表的結(jié)構(gòu)都一樣;每個表的數(shù)據(jù)都不一樣,沒有交集;所有表的并集是全量數(shù)據(jù)。 場景:系統(tǒng)絕對并發(fā)量并沒有上來,只是單表的數(shù)據(jù)量太多,影響了 SQL 效率,加重了 CPU 負擔,以至于成為瓶頸。 分析:表的數(shù)據(jù)量少了,單次 SQL 執(zhí)行效率高,自然減輕了 CPU 的負擔。 
 概念:以表為依據(jù),按照業(yè)務(wù)歸屬不同,將不同的表拆分到不同的庫中。 結(jié)果:每個庫的結(jié)構(gòu)都不一樣;每個庫的數(shù)據(jù)也不一樣,沒有交集;所有庫的并集是全量數(shù)據(jù)。 場景:系統(tǒng)絕對并發(fā)量上來了,并且可以抽象出單獨的業(yè)務(wù)模塊。 分析:到這一步,基本上就可以服務(wù)化了。例如,隨著業(yè)務(wù)的發(fā)展一些公用的配置表、字典表等越來越多,這時可以將這些表拆到單獨的庫中,甚至可以服務(wù)化。再有,隨著業(yè)務(wù)的發(fā)展孵化出了一套業(yè)務(wù)模式,這時可以將相關(guān)的表拆到單獨的庫中,甚至可以服務(wù)化。 
 概念:以字段為依據(jù),按照字段的活躍性,將表中字段拆到不同的表(主表和擴展表)中。 結(jié)果:每個表的結(jié)構(gòu)都不一樣;每個表的數(shù)據(jù)也不一樣,一般來說,每個表的字段至少有一列交集,一般是主鍵,用于關(guān)聯(lián)數(shù)據(jù);所有表的并集是全量數(shù)據(jù)。 2.6.3 分庫分表工具目前市面上的分庫分表中間件相對較多,其中基于代理方式的有 MySQL Proxy 和 Amoeba, 基于 Hibernate 框架的是 Hibernate Shards,基于 jdbc 的有當當 sharding-jdbc, 基于 mybatis 的類似 maven 插件式的有蘑菇街的蘑菇街 TSharding, 通過重寫 spring 的 ibatis template 類的 Cobar Client。 還有一些大公司的開源產(chǎn)品:  3.分布式數(shù)據(jù)庫3.1 什么是分布式數(shù)據(jù)庫分布式系統(tǒng)數(shù)據(jù)庫系統(tǒng)原理(第三版)中的描述:“我們把分布式數(shù)據(jù)庫定義為一群分布在計算機網(wǎng)絡(luò)上、邏輯上相互關(guān)聯(lián)的數(shù)據(jù)庫。分布式數(shù)據(jù)庫管理系統(tǒng)(分布式 DBMS)則是支持管理分布式數(shù)據(jù)庫的軟件系統(tǒng),它使得分布對于用戶變得透明。有時,分布式數(shù)據(jù)庫系統(tǒng)(Distributed Database System,DDBS)用于表示分布式數(shù)據(jù)庫和分布式 DBMS 這兩者。 在以上表述中,“一群分布在網(wǎng)絡(luò)上、邏輯上相互關(guān)聯(lián)”是其要義。在物理上一群邏輯上相互關(guān)聯(lián)的數(shù)據(jù)庫可以分布式在一個或多個物理節(jié)點上。當然,主要還是應(yīng)用在多個物理節(jié)點。這一方面是 X86 服務(wù)器性價比的提升有關(guān),另一方面是因為互聯(lián)網(wǎng)的發(fā)展帶來了高并發(fā)和海量數(shù)據(jù)處理的需求,原來的單物理服務(wù)器節(jié)點不足以滿足這個需求。 3.2 分布式數(shù)據(jù)庫的理論基礎(chǔ)1. CAP 理論首先,分布式數(shù)據(jù)庫的技術(shù)理論是基于單節(jié)點關(guān)系數(shù)據(jù)庫的基本特性的繼承,主要涉及事務(wù)的 ACID 特性、事務(wù)日志的容災(zāi)恢復(fù)性、數(shù)據(jù)冗余的高可用性幾個要點。 其次,分布式數(shù)據(jù)的設(shè)計要遵循 CAP 定理,即:一個分布式系統(tǒng)不可能同時滿足 一致性( Consistency ) 、可用性 ( Availability ) 、分區(qū)容 忍 性 ( Partition tolerance ) 這三個基本需求,最 多只能同時滿足其中的兩項, 分區(qū)容錯性 是不能放棄的,因此架構(gòu)師通常是在可用性和一致性之間權(quán)衡。這里的權(quán)衡不是簡單的完全拋棄,而是考慮業(yè)務(wù)情況作出的犧牲,或者用互聯(lián)網(wǎng)的一個術(shù)語“降級”來描述。 CAP 三個特性描述如下 :一致性:確保分布式群集中的每個節(jié)點都返回相同的 、 最近 更新的數(shù)據(jù) 。一致性是指每個客戶端具有相同的數(shù)據(jù)視圖。有多種類型的一致性模型 , CAP 中的一致性是指線性化或順序一致性,是強一致性。 可用性:每個非失敗節(jié)點在合理的時間內(nèi)返回所有讀取和寫入請求的響應(yīng)。為了可用,網(wǎng)絡(luò)分區(qū)兩側(cè)的每個節(jié)點必須能夠在合理的時間內(nèi)做出響應(yīng)。 分區(qū)容忍性:盡管存在網(wǎng)絡(luò)分區(qū),系統(tǒng)仍可繼續(xù)運行并 保證 一致性。網(wǎng)絡(luò)分區(qū)已成事實。保證分區(qū)容忍度的分布式系統(tǒng)可以在分區(qū)修復(fù)后從分區(qū)進行適當?shù)幕謴?fù)。 2. BASE 理論 基于 CAP 定理的權(quán)衡,演進出了 BASE 理論 ,BASE 是 Basically Available(基本可用)、Soft state(軟狀態(tài))和 Eventually consistent(最終一致性)三個短語的縮寫。BASE 理論的核心思想是:即使無法做到強一致性,但每個應(yīng)用都可以根據(jù)自身業(yè)務(wù)特點,采用適當?shù)姆绞絹硎瓜到y(tǒng)達到最終一致性。 BA:Basically Available 基本可用,分布式系統(tǒng)在出現(xiàn)故障的時候,允許損失部分可用性,即保證核心可用;S:Soft state 軟狀態(tài),允許系統(tǒng)存在中間狀態(tài),而該中間狀態(tài)不會影響系統(tǒng)整體可用性;E:Consistency 最終一致性,系統(tǒng)中的所有數(shù)據(jù)副本經(jīng)過一定時間后,最終能夠達到一致的狀態(tài)。 BASE 理論本質(zhì)上是對 CAP 理論的延伸,是對 CAP 中 AP 方案的一個補充。 3.3 分布式數(shù)據(jù)庫的架構(gòu)演變
 
 | 
|  | 
來自: 520jefferson > 《sql》