《App後臺開發運維與架構實踐》第6章 MySQL數據庫

6.1 基本架構

  • 服務層

大多數基於網絡的客戶端/服務端工具都有這一層,這一層主要是處理鏈接和安全驗證。mysql

  • 核心層

這層處理MySQL的核心業務。查詢分析、優化、緩存和內存的函數;內建的視圖,存儲過程,觸發器。sql

  • 存儲引擎層

存儲引擎負責數據的存儲和提取。核心層經過存儲引擎的API與存儲引擎通訊,這樣子就遮蔽了不一樣存儲引擎的差別,使得這些差別對上層查詢是透明的。存儲引擎之間不會相互通訊,只是簡單地響應上層的查詢。數據庫

6.2 選擇版本

MySQL的發展經歷了下面的幾個里程碑。緩存

  • 1979年,創始人Monty Windenius寫了最初的版本。
  • 1996年,發佈1.0版本。
  • 1995-2000年,MySQL AB公司成立,引入BDB。
  • 2000年,集成MyISAM和Replication。
  • 2008年,MySQL AB被Sun收購,2009年推出5.1版本。
  • 2009年,Oracle收購Sun,2010年12月推出5.5版本。

MySQL被Oracle收購後,MySQL創始人Monty Windenius主導開發了MariaDB,採用GPL受權許可,徹底兼容MySQL,使用XtraDB存儲引擎來代替MySQL的InnoDB存儲引擎。安全

因爲上面所述的歷史緣由,形成了如今有4個MySQL的版本。服務器

  • MySQL社區版:用戶羣體最大。
  • MySQL企業版:收費。
  • Percona Server版:新特性多。
  • MariaDB版:國內用戶很少。

建議開發者選擇MySQL社區版,足夠應付業務上的需求。網絡

6.3 配置文件詳解

在Linux中MySQL的配置文件是/etc/my.cnf。多線程

6.4 軟件優化

6.4.1 正確使用MyISAM和InnoDB存儲引擎

在MySQL 5.1版本中,默認的存儲引擎是MyISAM;到了MySQL 5.五、5.6版本,默認的存儲引擎是InnoDB。架構

MyISAM基於ISAM(索引順序訪問方法),支持全文索引,但並不是事務安全,不支持外鍵,使用表級鎖。每一個MyISAM表存有3個文件:FRM文件存放表結構,MYD文件存放數據,MYI存放索引。負載均衡

InnoDB是事務性存儲引擎,其支持行鎖,InnoDB表的行鎖也不是絕對的,若是它在執行一個更新的語句時無法肯定更新的範圍,也會鎖表。InnoDB支持回滾、崩潰恢復、ACID事務控制,InnoDB存儲它的表和索引在一張表空間,表空間能夠包含多個文件。

MyISAM和InnoDB的主要區別以下。

  • MyISAM支持表鎖,InnoDB支持行鎖。
  • MyISAM是非事務安全型,InnoDB是事務安全型。
  • MyISAM不支持外鍵,InnoDB支持外鍵。

6.4.2 正確使用索引

使用索引的一些原則。

  • 給合適的列創建索引

在where子句中常常須要給檢索的列創建索引,或者給鏈接子句中指定的列創建索引,而不是給select選擇列表中的列創建索引。

  • 索引列的值儘量不一樣

對於有惟一性的值,索引的效果最好;若是有大量的重複值,索引的效率不好。

  • 使用短索引

對字符類型的列創建索引,只要有可能,都應該指定前綴長度。

  • 利用最左前綴

建立一個n列索引,本質上是MySQL建立了n個索引。多個索引能夠起n個索引的做用,能夠用索引中最左列的值來匹配,這樣的列值叫作最左前綴。

  • 使用like查詢時索引會失效

儘可能少使用like查詢,對於百萬、千萬級的數據,能夠採用專業的搜索軟件來實現。

  • 不能濫用索引

索引不是越多越好,使用索引須要恰到好處。過分使用索引會有下面的問題:索引會佔用額外的磁盤空間,下降性能;當更新數據時索引必須更新,花費時間更長;有可能使MySQL選擇到不是最優的索引,增長查詢優化的時間。

6.4.3 避免使用select *

使用「select *」有下面的壞處:

  • 在select語句執行的過程當中,「select *」從數據庫中返回的結果更多,下降了查詢的速度。
  • 過多的返回結果會增大服務器返回給App端的數據的傳輸量。過大的傳輸量很容易形成請求的失效。

6.4.4 字段儘量地設置爲NOT NULL

6.5 硬件優化

6.5.1 增長物理內存

MySQL讀寫數據最大的性能瓶頸就是磁盤IO,從減小磁盤IO方面提升性能是個重要的方向。經過加大物理內存能夠採起提高文件系統性能,減小磁盤IO。另外,MySQL中也用了大量的內存來提升性能,配置參數以下。

  • thread_cache_size:服務端線程緩存。
  • sort_buffer_size:每一個鏈接須要使用buffer時,分配的內存大小。
  • query_cache_size:查詢緩存的大小。
  • query_cache_limit:單次查詢緩衝區的大小。

6.5.2 增長應用緩存

把應用的熱數據存儲在緩存中,若是緩存中有數據就不須要到數據庫讀取數據,從而達到提升性能的目的。

應用的緩存有如下兩種。

  • 本地緩存:把數據放在服務器的內存或文件中。
  • 分佈式緩存:Redis(數據能夠持久化)或Memcache。

6.5.3 用固態硬盤代替機械硬盤

6.5.4 SSD硬盤+SATA硬盤混合存儲方案

6.6 架構優化

6.6.1 分表

當項目上線後,隨着用戶的增加,有些數據表的規模會以幾何級增加,當數據達到必定規模後查詢讀取性能就降低不少,這時要考慮分表了。

  • 水平拆分:把一張表的數據分別保存在不一樣的表。
  • 垂直拆分:把一張表的字段分別保存在不一樣的表。

分表的存儲引擎是MyISAM,能夠利用MERGE存儲引擎將拆分的表合併成一張表。若是是InnoDB,也能經過alter table命令把InnoDB變爲MyISAM。

6.6.2 讀寫分離

隨着App的不斷迭代和推廣,數據不斷增多,數據庫的壓力也愈來愈大,對MySQL的基礎優化可能達不到最終的效果。所以採起數據庫的讀寫分離策略進行優化。

讀寫分離是把對數據庫的讀和寫操做分開對應於主/從數據庫服務器,主數據庫提供寫操做,從數據庫提供讀操做(能夠有多個數據庫)。由於大多數業務是以讀爲主,所以多個從數據庫能有效減輕數據庫的壓力。

當主數據庫進行寫操做時,數據要同步到從數據庫,這樣纔能有效保證數據庫完整性。這稱爲數據庫的主從複製。

MySQL主從複製基於主服務器在二進制日誌(binlog)中跟蹤全部對數據庫的更改實現。所以要進行復制,必須在主服務器上啓用二進制日誌。

主從複製的延遲問題,通常來講從數據庫的壓力比主數據庫大多了,很是容易致使延遲。

延遲的解決方案以下。

  • 定位延遲的瓶頸,若是是由於IO壓力大,那麼能夠考慮採用升級硬件的方案,如把硬盤更換爲SSD硬盤。
  • 若是是由於單線程從relaylog中執行MySQL語句致使延遲,能夠採用MySQL 5.6以上版本的多線程方案,或者採用Tungsten爲表明的第三方並行複製工具。
  • 若是以上兩種方案都不起做用,就要考慮採用分庫策略。

6.6.3 分庫

當數據規模不斷增打,分表和讀寫分離可能都知足不了系統的性能需求,這時須要考慮分庫,即把不一樣的數據表部署到不一樣的數據庫集羣上。

支持數據庫分庫的關係型數據庫分佈式處理軟件Mycat,它以代理服務器的形式位於應用服務器與後臺數據庫之間,因爲其是無狀態,所以很容易部署MyCat集羣實現負載均衡。對外開放的接口是MySQL通訊協議,將應用服務器傳過來的SQL語句按照路由的規則拆解轉發到不一樣的後臺數據庫,並把結果彙總並返回。

MyCat能夠把一個邏輯上的數據庫和數據表對應到物理上真實的數據庫和數據表,用戶只須要按照邏輯上的結構操做相關數據就行,遮蔽了物理上的差別。

6.7 SQL慢查詢優化

SQL慢查詢是指執行超過必定時間的SQL查詢語句,把這些SQL查詢語句記錄到慢查詢日誌,方便開發人員找出有性能問題的SQL,針對這些SQL查詢語句進行分析調優。

配置選項中慢查詢相關的3個參數以下。

  • long_query_time:定義慢查詢的時間,SQL查詢語句執行時間大於該參數設置時間的SQL都會被記錄下來,支持小於1秒的設置。
  • slow_query_log:設置是否打開慢查詢日誌的開關。
  • slow_query_log_file:設置慢查詢日誌文件的路徑。

配置慢查詢有兩種方法。

  • 經過命令行設置,當即生效,可是在MySQL服務重啓後失效。
set global long_query_time=1;
set global slow_query_log=on;
set global slow_query_log_file='/data/slow.log';
  • 在/etc/my.conf中新增下面的配置選項,重啓MySQL服務後生效。
[MySQLd]
long_query_time=1
slow_query_log=on
slow_query_log_file=/data/slow.log

可使用MySQL自帶的工具mysqldumpslow分析慢查詢日誌,例如,查看最慢的前3個SQL查詢的命令格式以下。

mysqldumpslow -t 3 /data/slow.log

開啓慢查詢日誌後,可在系統狀態中查看慢查詢數。

show global status like '%slow%';

要分析慢查詢語句,須要使用到MySQL的explain命令。

相關文章
相關標籤/搜索