【阿里線上技術峰會】羅龍九:雲資料庫十大經典案例分析
本文根據阿里雲資深DBA專家羅龍九在首屆阿里巴巴線上峰會的《雲資料庫十大經典案例分析》的分享整理而成。羅龍九以MySQL資料庫為例,分析了自RDS成立至今,使用者在使用RDS過程中最常見的問題,包括:索引、SQL優化、鎖、延遲、引數優化、連線數、CPU、Iops、磁碟、記憶體等。羅龍九通過對十大經典案例的總結,還原問題原貌,給出分析問題的思路,旨在幫助使用者在使用RDS的路上少一些彎路,多一些從容。
以下為整理內容。
案例一:索引
今天之所以將索引放在第一位進行分享,是因為索引的問題出現頻率是最高的。常見的索引問題包括:無索引、隱式轉換兩類。其中隱式轉換是由SQL傳入的值和表結構定義的資料型別不一致引起;或者是表字段定義的
在使用索引時,我們可以通過explain(extended)檢視SQL的執行計劃,判斷是否使用了索引以及發生了隱式轉換。由於常見的隱式轉換是由欄位資料型別以及collation定義不當導致,因此我們在設計開發階段,要避免資料庫欄位定義,避免出現隱式轉換。此外,由於MySQL不支援函式索引,在開發時要避免在查詢條件加入函式,例如date(gmt_create)。最後,所有上線的SQL都要經過嚴格的稽核,建立合適的索引。
案例二:SQL優化
SQL優化是很多使用者都需要面對的問題。我們在不斷地優化、除錯過程中總結了三類SQL優化的最佳實踐,分別是分頁優化、子查詢優化、查詢需要的欄位。
分頁優化
select * from buyer where sellerid=100 limit 100000,5000
這條語句是普通的Limit M、N的翻頁寫法,在越往後翻頁的過程中速度越慢,這是由於MySQL會讀取表M+N條資料,M越大,效能越差。
我們通過採用高效的Limit寫法,可以將上述語句改寫成:
select t1.* from buyer t1,
(select id from buyer sellerid=100 limit 100000,5000) t2
where t1.id=t2.id;
從而避免分頁查詢給資料庫帶來效能影響。需要注意一點是,這裡需要在t表的sellerid欄位上建立索引,id為表的主鍵。
子查詢優化
子查詢在MySQL5.1、5.5版本中都存在較大的風險。這是一段典型子查詢SQL程式碼:
SELECT first_name
FROM employees
WHERE emp_no IN
(SELECT emp_no FROM salaries_2000 WHERE salary = 5000);
由於MySQL的處理邏輯是遍歷employees表中的每一條記錄,代入到子查詢中去 。所以當外層employees表越大時,迴圈次數也隨之增多,從而導致資料庫效能的下降。
這是我們改寫子查詢之後的SQL程式碼:
SELECT first_name
FROM employees emp,
(SELECT emp_no FROM salaries_2000 WHERE salary = 5000) sal
WHERE emp.emp_no = sal.emp_no;
首先將子查詢的結果放到臨時表內,再去和employees表做關聯。此外,使用者也可以選擇使用Mysql 5.6的版本,避免麻煩的子查詢改寫。
查詢需要的欄位
在訪問資料庫時,應該儘量避免使用SELECT *查詢所有欄位資料,只查詢需要的欄位資料。
案例三:鎖
在使用資料庫時,每個人或多或少都會碰到鎖的問題。在設計開發階段,我們需要注意這三點問題:一是避免使用myisam儲存引擎,改用innodb引擎;二是注意避免大事務,這是因為長事務導致事務在資料庫中的執行時間加長,造成鎖等待;三是選擇將資料庫升級到支援online ddl的MySQL 5.6版本。
在管理運維階段,我們可以從四點出發搞定鎖的問題:
- 在業務低峰期執行上述操作,比如建立索引,新增欄位;
- 在結構變更前,觀察資料庫中是否存在長SQL,大事務;
- 結構變更期間,監控資料庫的執行緒狀態是否存在lock wait;
- RDS支援在DDL變更中加入 wait timeout。
案例四:延遲
由於資料庫架構大多是主備的方式,延遲便成了一個常見的問題。產生延遲的原因有很多,例如在只讀例項架構中,主備節點間MySQL原生複製實現資料同步方式會天然導致延遲的產生。此外,create index、repair等常見DDL操作、大事務、MDL鎖以及資源問題都會導致延遲的出現。
處理延遲問題,需要具有清晰的排除思路:一看資源是否達到瓶頸;二看執行緒狀態是否有鎖;三判斷是否存在大事務。同時我們還可以通過使用innodb儲存引擎、將大事務拆分為小事務、DDL變更期間觀察是否有大查詢等具體最佳實踐降低延遲。
案例五:引數優化
我們曾經遇到這樣一個案例,某金融客戶在將本地的業務系統遷移上雲後,在最高配置的RDS上執行時間明顯要比線下自建資料庫執行時間慢1倍,進而導致客戶系統出現割接延期的風險。對於這類案例的分析,根據以往的經驗,可以從以下三點出發:
- 首先檢視資料庫是否是跨平臺遷移(PG->MySQL、ORALCE->MySQL);
- 其次檢視是否是跨版本升級(MySQL:5.1->5.5、5.5->5.6),不同的版本之間是有差異的;
- 如果上述兩點都不存在,則需要檢視具體的執行計劃、優化器、引數配置、硬體配置。
如果SQL從雲下遷移到雲上或者從一個版本遷移到另一個版本的過程中出現效能問題時,要保持清晰的排查思路:從SQL執行計劃到資料庫版本和優化器規則,再到引數(包括Query_cache_size、Temp_table_size)配置和硬體配置等一一進行排查。曾經看到這樣一個案例,一個使用者使用預設的mysql配置跑線上應用,db所在的主機的記憶體有500G,但是分配給MySQL的記憶體確是預設的128M,導致了整個系統的效能下降。
案例六:CPU 100%最佳實踐
導致CPU 100%的三大因素分別是:慢SQL、鎖和資源。對於慢SQL問題:我們可以通過優化索引或者通過避免子查詢、隱式轉換以及進行分頁改寫等措施從根上解決該問題。對於鎖等待問題:可以通過設計開發和管理運維優化鎖等待。對於資源問題:可以通過引數優化、彈性升級、讀寫分離、資料庫拆分等方式優化。
案例七:Conm 100%
導致Conm 100%的三大因素分別是慢SQL、鎖、配置。對於慢SQL問題:解決方案類似於處理CPU 100%,同樣是通過優化索引或者通過避免子查詢、隱式轉換以及進行分頁改寫等措施從根上解決該問題。對於鎖等待問題:同樣可以通過設計開發和管理運維優化鎖等待。對於配置問題:我們需要合理規劃資料庫上的連線數的使用,避免客戶端連線池引數配置超過例項最大連線數的情況出現。此外,還可以通過彈性升級RDS的規格配置來滿足客戶端需要的連線數。
案例八:Iops 100%
Iops 100%也是一個很常見的問題。導致Iops 100%的原因也可以分為慢SQL問題、DDL、配置問題三類。對於慢SQL問題:解決方案同樣類似於處理CPU 100%問題,通過優化索引或者通過避免子查詢、隱式轉換以及進行分頁改寫等措施從根上解決該問題。對於DDL問題:一定要避免併發進行create index、optimze table、alter table add column等操作;同時這些操作最好在業務低峰期進行。對於配置問題:可以通過彈性升級RDS的規格配置解決。
案例九:disk 100%
磁碟空間由資料檔案、日誌檔案和臨時檔案組成。對於資料空間問題:由於資料檔案的索引和資料是放在一起的,當對錶刪除資料後可以採用optimize table收縮表空間,同時刪除不必要的索引;對於寫多讀少的應用,可以使用tokudb壓縮引擎進行表壓縮。對於日誌空間問題:首先我們需要減少大欄位的使用;其次可以使用truncate替代delete from。對於臨時空間問題:一是可以適當地調大sort_buffer_size;二是可以建立合適索引避免排序。
案例十:mem 100%
當記憶體使用率達到100%時,作業系統會kill掉MySQL程序,從而導致業務的中斷。因此,我們需要明確地瞭解資料庫的記憶體使用詳情。資料庫記憶體主要由Buffer pool size 、Dictionary memory、Thread cost memory三部分組成。對於Buffer pool size問題:首先,我們可以通過建立合適的索引,避免大量的資料掃描;其次,我們需要去除不必要的索引,降低記憶體的消耗。對於Thread cost memory問題:一方面,我們可以通過建立合適的索引避免排序;另一方面,在查詢資料時,我們只查詢應用所需的資料,避免所有資料的查詢。對於Dictionary memory問題:當表被訪問開啟後其元資料資訊是儲存在Dictionary memory之中的,過度的分表會導致記憶體的大量佔用,因此分表時要注意把握分寸,不多過度分表,曾經看到一個數據庫中建立了十幾萬張表。
關於分享嘉賓:
羅龍九,阿里雲資深DBA專家,有著豐厚的DBA經驗,經歷阿里歷年雙11考驗,負責阿里雲RDS線上穩定以及專家服務團隊,積累了6年對阿里雲資料庫使用者的運維、調優、診斷等豐富的經驗。
掃我,和雲棲線上交流
【雲棲快訊】首屆阿里巴巴線上技術峰會,將於7月19日-21日20:00-21:30線上舉辦。峰會邀請到阿里集團9位技術大V,分享電商架構、安全、資料處理、資料庫、多應用部署、互動技術、Docker持續交付與微服務等一線實戰經驗,解讀最新技術在阿里集團的應用實踐。 詳情請點選