讓天下沒有難用的資料庫 » RDS最佳實踐(三)
上一篇文章中,我們介紹瞭如何快速的把本地自建的資料庫遷移入雲,那是不是把資料庫遷移到RDS後,使用者就什麼都不需要做了?比如RDS幫你的資料庫做到了高可用,在主庫出現down機後能夠快速切換到備庫,立刻恢復應用;每天會定時的備份資料和日誌,如果出現誤操作能夠幫你恢復到任意時間點;如果擔心黑客攻擊或者sql注入漏洞,RDS能夠幫助你進行sql注入的攔截;當資料庫使用中出現bug時,後端有專業的原始碼和DBA團隊幫助使用者例項打上patch,讓使用者無後顧之憂;當例項的效能出現瓶頸的時候,可以進行快速的彈性升級,保證服務的正常執行等等。
可以看到RDS已經具備相當豐富的自動化資料庫運維的功能,使用者不用太關心後端資料庫的運維,以前這些非常專業的DBA工作完完全全可以交由RDS系統來完成,那麼還需要使用者做什麼,是不是不需要使用者干預了?答案是需要的,在日常的工單問題發現:
一. 經常會發現由於自己的開發人員誤操作導致使用者資料被誤刪除,雖然RDS支援恢復到任意時間點,但畢竟需要時間去恢復,會造成對使用者的影響;所以線上的操作務必謹慎,必須在測試環境中完全驗證後才能到線上執行,同時需要必要的資料備份;
二.開發人員釋出了一個新功能,但是新功能中的一條sql語句沒有新增索引,導致了全表掃描,RDS的CPU,IO達到100%,影響了整個應用的響應時間;所以新發布的任何sql都必須進過嚴格的稽核,新增上必要的索引;
三. 開發人員在業務高峰期對錶進行一個表新增索引或者新增欄位的操作(刪除資料),導致該表的其他訪問堵塞,影響前端應用;所以任何的線上操作都需要在業務的低峰期進行,生產變更必須嚴格控制在可允許的變更視窗內;
四.RDS例項由於時間到期後沒有及時進行處理,導致例項被鎖定或者釋放,雖然最終資料可以恢復回來,但這種故障的發生往往令人心驚膽寒;
所以需要使用者制定出合理的流程規範來使用RDS,比如設計開發過程中的資料庫流程規範,線下測試環境與線上生產環境資料的匯入匯出流程規範,線上資料訂正的流程規範,線上資料庫操作(新增欄位,新增索引)的流程規範,資料庫上線下線的流程規範。
在阿里巴巴資料庫技術團隊,即使有了非常自動化的運維平臺,上述的這些流程制定也是開發,測試,DBA都必須遵守的,就是因為有了上述的這些流程才避免了很多不必要的故障發生,大大提高了整個平臺的穩定性,除此之外還制定了運維紅線:
一.禁止在非變更視窗執行變更:
.所有的變更必須提前4小時提交申請,進過審批後才能執行操作;
.全網變更必須經過線下測試,線上小規模驗證後,才能全網推送;
.重大變更(資料庫停機,擴容,遷移)必須團隊review;
.資料訂正和資料提取必須經過團隊leader稽核通過後才能進行操作;
二.安全保密:
.禁止未經正式審批進行查閱,變更,傳播,移動線上資料;
.禁止對無關人員提供系統登入和釋出許可權;
資料庫開發規範:趕集網(國內網際網路公司)的DBA 吳詩展把自己多年的資料庫mysql運維開發檢驗總結了—MySQL資料庫開發的三十六條軍,對於很多的RDS使用者來說同樣是很受用的,包括了:基本軍規,欄位軍規,索引軍規,SQL類軍規,約定類軍規,在此也很感謝他能夠把多年來的經驗總結分享給眾多的資料庫使用者,在這裡也在著重強調一些比較重要的規範:
一.表主鍵的設定:自增主鍵是你的最佳選擇
.在設計表的時候預設都新增一列無業務意義的自增id的主鍵:id bigint not null auto_increment;
.自增型主鍵以利於插入效能的提高
.自增型主鍵設計(int,bigint)可以降低二級索引的空間,提升二級索引的記憶體命中率;
.自增型的主鍵可以減小page的碎片,提升空間和記憶體的使用;
.無主鍵的表刪除,更新在row模式的主從架構,會導致備庫hang住;
二.引擎選擇:INNODB 引擎是你的最佳選擇
使用INNODB儲存引擎還是Myisam儲存引擎?
.RDS的記憶體配置innodb的innodb_buffer_pool_size,Myisam的key_cache配置32k;
.主機斷電,crash後Myisam表容易出現索引壞葉,需要手工repair修復索引;
.Myisam儲存引擎的表備份時候會被全域性鎖住,導致無法寫入資料;
案例一:下面的這幅圖片就是myisam引擎的表由於一個大查詢堵塞了該表的其他更新:
案例二:.FEDERATED 儲存引擎使用存在bug,會導致備份失敗
error log: >> log scanned up to (867972807) 130616 00:00:58 innobackupex-1.5.1: Continuing after ibbackup has suspended 130616 00:00:58 innobackupex-1.5.1: Starting mysql with options: –defaults-file=’/etc/my3015.cnf’ –password=xxxxxxxx –user=’Xtrabak’ –host=’127.0.0.1′ –port=’3015′ –unbuffered — 130616 00:00:58 innobackupex-1.5.1: Connected to database with mysql child process (pid=31437) 130616 00:01:00 innobackupex-1.5.1: Starting to lock all tables… >> log scanned up to (867972807) innobackupex-1.5.1: Error: mysql child process has died: ERROR 1160 (08S01) at line 7: Got an error writing communication packets while waiting for reply to MySQL request: ‘FLUSH TABLES WITH READ LOCK;’ at /usr/bin/innobackupex-1.5.1 line 381. 2013-06-16 00:01:06 [info]: Xtrabackup error,you can get detail from Logfile. 2013-06-16 00:01:06 [info]: ====================================== All backup finished . |
三.索引設計誤區:
誤區案例一:對查詢條件的每個欄位建立單列索引
SQL查詢:
SELECT count(*) FROM order o WHERE is_send=0 AND
o.order_status in (0,1) AND o.shipping_status = 0 AND
o.is_separate > 0 and o.is_yushou=0 and o.sd_id=23
and o.add_time>= ‘1370246433’ and o.add_time<= ‘1370332842’
and o.jhd_id=0 group by o.order_id;
KEY:該表有近30個索引
PRIMARY KEY (order_id), UNIQUE KEY order_sn (order_sn), UNIQUE KEY deal_code (deal_code), KEY ind_user_id (user_id), KEY ind_shipping_id (shipping_id), KEY ind_pay_id (pay_id), KEY ind_agency_id (agency_id), KEY ind_extension_id (extension_id) , KEY ind_order_id (order_id), KEY ind_delivery_time (delivery_time) , KEY ind_invoice_no (invoice_no), KEY ind_user_nick (user_nick), KEY idx_cz_shipping_fee (cz_shipping_fee), KEY ind_mobile (mobile), KEY ind_order_info_sd (sd_id,is_send,add_time), KEY ind_order_info_status (shipping_status), KEY ind_order_pay_status (pay_status), KEY ind_order_is_yushou (is_yushou), KEY ind_order_dist_type (dist_type), KEY ind_order_jhd_id (jhd_id), KEY ind_order_is_send (is_send), KEY ind_order_ck_id(ck_id ), KEY ind_order_is_separate(is_separate), KEY ind_consignee (consignee), KEY ind_order_info_lylx (lylx,order_status,is_send); |
索引設計誤區二:對查詢的所有欄位建立組合索引
09:44:03> show table status like ‘order’\G; *************************** 1. row *************************** Name: order Engine: InnoDB Version: 10 Row_format: Compact Rows: 5708209 Avg_row_length: 357 Data_length: 2042626048 Max_data_length: 0 Index_length: 9014607872 Data_free: 5242880 Auto_increment: NULL Create_time: 2013-04-09 22:56:57 Update_time: NULL Check_time: NULL Collation: utf8_bin Checksum: NULL Create_options: omment: 訂單表 該表的資料只有2G,但是索引卻佔用了9個G: |
KEY `idx_plt_taobao_order_dp_id` (`dp_id`,`customerno`,`created`,`endtime`,`pay_time`,`modified`,`consign_time`,`payment`,`status`,`type`,`total_fee`,`refund_fee`,`num`,`received_payment`,`trade_from`,`ccms_order_status`) KEY `idx_plt_taobao_order_created` (`created`,`customerno`,`endtime`,`pay_time`,`modified`,`consign_time`,`payment`,`status`,`type`,`total_fee`,`refund_fee`,`num`,`received_payment`,`trade_from`,`dp_id`,`ccms_order_status`) KEY `idx_plt_taobao_order_endtime` (`endtime`,`customerno`,`created`,`pay_time`,`modified`,`consign_time`,`payment`,`status`,`type`,`total_fee`,`refund_fee`,`num`,`received_payment`,`trade_from`,`dp_id`,`ccms_order_status`) KEY `idx_plt_taobao_order_pay_time` (`pay_time`,`customerno`,`created`,`endtime`,`modified`,`consign_time`,`payment`,`status`,`type`,`total_fee`,`refund_fee`,`num`,`received_payment`,`trade_from`,`dp_id`,`ccms_order_status`) |
希望這篇blog能夠對你使用RDS有所幫助.