1. 程式人生 > 實用技巧 >分享一份公司DBA發的mysql資料庫開發規範文件

分享一份公司DBA發的mysql資料庫開發規範文件

規範 - mysql開發規範

MySQL安全

賬號分類

  1. 管理員帳戶(DBA專用)
  2. 運維類帳戶(複製,監控,備份等)
  3. 程式用賬戶(根據業務命名,許可權最小化原則.命名規則: 業務_rw, 業務_r)
  4. 只讀用賬戶(根據內外網決定是否啟用SSL)

開發許可權

  1. 程式帳戶許可權:

​ *_rw賬號許可權: SELECT,INSERT,UPDATE,DELETE,SHOW VIEW

​ *_r賬號許可權: SELECT,SHOW VIEW,EXECUTE(不改寫資料)

其它安全規範

  1. 禁止使用程式帳號通過客戶端訪問資料庫,使用OPS系統
  2. 連線串中密碼必須加密
  3. 生產環境限定帳戶的Host為內網段IP。例: au_business_r@’10.10.7.%’
  4. 許可權預設給5+2(可選)種: insert,delete,update,select,show view; execute,mysql.proc select許可權
  5. DB伺服器禁用外網IP。如果需要外網訪問使用ip+port轉發方式並使用SSL加密資料
  6. 禁用連結伺服器(FEDERATED引擎)
  7. 禁止drop表,可以rename table到backupdb資料庫,後續刪除
  8. 刪除無用賬號

SQL上線流程

指令碼化

  1. 描述清楚本次上線的目的和步驟
  2. 必須以指令碼的形式提供給DBA,無法指令碼化時寫出詳細步驟
  3. 必須限定到某個資料庫: ip+port+database
  4. 不同的mysql例項,不同的業務,拆分成多個指令碼。目的:清晰,出錯易排查,易回滾
  5. DDL和DML指令碼分開。先執行DDL,後執行DML
  6. 需要按順序執行的指令碼,在指令碼名或指令碼中指定順序
  7. 涉及到原子操作,必須顯示宣告事務(begin; … commit;)
  8. 對同一個表的多次DDL操作合併為一次操作(更改主鍵除外)

郵件模板

業務描述:XXX上線【備註和注意事項也寫在這裡】

執行時間:現在/2018-06-01 22:00/研發通知

mysql: 192.168.1.1:3306 【注:還可能有sqlserver等】

db: au_business 【資料庫名稱】

SQL(共3步): 【注: 如有步驟,請描述,需要考慮回滾方案】

第1步:檢查xxx正確性,備份xxx表

select count(*) as cnt from tb_city where city_id in(1,2); #2條記錄則正常

第2步:更新xxx的值

begin;

update tb_city set city_name='北京', city_type='5' where city_id = 1;

update tb_city set city_name='深圳', city_type='5' where city_id = 2;

commit;

第3步:增加xxx商品

insert into tb_city(city_name, city_type) values('上海', '5'), ('香港', '1'); #儘量批量提交

注:

  1. 附件較大時請壓縮
  2. 附件名稱可加1,2,3備註
  3. 資料庫有多個時,SQL指令碼中加上use dbname;

Review

  1. 先了解清楚指令碼的目的和步驟
  2. 檢查指令碼是否符合資料庫開發規範
  3. 檢查指令碼是否存在bug(主要針對複雜SQL)
  4. 提出合理建議,總結規範
  5. DDL語句的稽核提前到開發,提測階段

上線

  1. 瞭解Move in相關的資料庫情況,確保不影響生產:庫大小,表大小,是否存在replication,是否鎖表等
  2. 耗時操作,儘量分段執行指令碼,有意外情況,及時回滾
  3. 業務相關INSERT,DELETE,UPDATE,SELECT通過OPS平臺操作,其餘通過DBA執行
  4. OPS平臺支援不了的功能,提交給DBA來完成

MysQL設計與開發規範

設計規範

  1. 【必須】庫與庫之間解耦,不允許跨庫查詢(dbname.tablename),同一DB例項上的庫與庫之間的查詢寫成多條SQL。資料庫由於效能原因遷移時,程式只用修改連線串。
  2. 【必須】不同業務間的資料互動統一通過介面進行,不使用複製技術
  3. 【建議】複製技術僅用於讀寫分離,高可用,報表平臺數據同步等

  1. 【必須】庫名、表名、欄位名,全部小寫(mysql引數 :lower_case_table_names=1),使用26個英文字母,下劃線,數字。只能以英文字母開頭, 不超過32個字元。須見名知意,命名與業務、產品線等相關聯。庫命名:根據業務起名,表命名:業務名稱_表作用。如:risk_service.tb_risk_config。測試環境庫名需與線上保持一致,多套DB環境時,字尾加資料區分:risk_service_2
  2. 【必須】統一單數形式,如訂單表:order,反例:orders
  3. 【強制】資料庫表、欄位必須加入中文註釋
  4. 【必須】庫名、表名、欄位名禁止使用MySQL保留字
  5. 【建議】欄位允許適當冗餘,減少JOIN,遵循規則:1. 不是頻繁修改的欄位2.不是varchar超長欄位
  6. 【建議】大欄位、訪問頻率低的欄位拆分到單獨的表中儲存,分離冷熱資料
  7. 【建議】臨時性的資料或者生命週期很短的資料等資訊,不放在資料庫
  8. 【建議】監控分析類日誌資料不建議儲存在MySQL上,優先考慮非關係型資料庫或檔案中,如需要與DBA評估使用壓縮表儲存欄位
  9. 關鍵業務需要加history表。除了儲存修改前的所有欄位,還需要增加修改人,修改時間,修改型別(update,delete)等至少3個欄位。
  10. 【建議】單表超過500W行或容量超過2G, 才考慮分庫分表,或歸檔處理
  11. 【建議】表設計時常問3個問題:表是否是核心業務資料?表讀寫頻率?資料量大小,是否可歸檔?
  12. 【必須】臨時庫、表名必須以tmp為字首,並以日期(20170101)為字尾,用完立刻刪除。
  13. 【必須】備份庫、表必須以bak為字首,並以日期(20170101)為字尾,可以加上其它說明。
  14. 【必須】臨時表,備份表儲存到備份庫(backupdb),定期清除。
  15. 【建議】總體原則:冷熱分離,減少JOIN,讀寫狀態,考慮併發

欄位

  1. 【必須】所有欄位必須not null + default約束,減少三值邏輯。特殊情況與DBA確認。
  2. 【必須】同一業務欄位在不同的表中的型別必須一致,防止JOIN時發生型別轉換。名稱必須一致,自增列除外,自增列統一命名id。
  3. 【必須】欄位佔用位元組越小越好,儘量用數字型別,用tinyint代替enum型別
  4. 【建議】Varchar長度不允許超過5000,如果超長,定義為text,需要與DBA確認
  5. 【建議】儘可能不用text,blob型別,確定需要找DBA確認
  6. 【必須】禁止使用float, double型別,用decimal, int等替代
  7. 【必須】根據業務情況定義varchar長度,儘量不超過255
  8. 【建議】禁止使用varchar型別作為主鍵語句設計
  9. 【必須】長度不變用char,否則統一用varchar,長度不超過255
  10. 【必須】status, type等欄位型別,範圍不超過正負255,統一用tinyint
  11. 【必須】表自增列名稱必須為id,型別為int/bigint,步長為1。
  12. 【建議】不使用unsigned型別,統一使用有符號型別int/bigint。
  13. 【建議】表必有create_time, 人為觸發新增資料的表必須有create_user欄位,有資料修改的表必須有update_time欄位, 人為觸發修改資料的表必須有update_user欄位,型別為datetime, 更新資料表記錄時,必須同時更新相關的update_time,update_user值。
  14. 【建議】欄位必有註釋,欄位含義變更時需要維護欄位註釋。建議格式為: 1=正常; 2=異常/不可用; 3=刪除

  1. 【必須】表必須有主鍵,可用自增列做主鍵。業務鍵作主鍵需要考慮效能
  2. 【必須】禁用外來鍵約束,由程式實現資料完整性
  3. 【必須】業務上需要進行唯一性約束的,必須加唯一鍵

索引

  1. 【建議】一個索引中的欄位數建議不超過5個,一張表中的索引數一般不超過10個
  2. 【建議】建表時加上可預見的索引
  3. 【必須】選擇性高的欄位放在前面,不在低基數列上建立索引(比如:性別欄位)
  4. 【必須】優化複合索引中的欄位順序
  5. 【必須】避免冗餘和重複索引
  6. 【必須】重要的SQL才加索引
  7. 【必須】僅除錯時允許使用 FORCE INDEX
  8. 【必須】索引命名規範:索引:ix_field1_field2;唯一索引:uix_field1_field2;主鍵:預設(PRIMARY)
  9. 【建議】varchar欄位建立索引,欄位較長時需要指定索引長度: CREATE INDEX ix_name ON customer(name(10));
  10. 【建議】適當使用覆蓋索引來優化查詢,避免回表。主要針對高併發或查詢資料量比較大的情景。
  11. 【注意】如果有 order by 的場景,請注意利用索引的有序性。反例:WHERE a>10 ORDER BY b; 索引a_b 無法排序

其它物件

  1. 【必須】禁止使用MySQL儲存過程,函式,觸發器,定時事件,檢視。

開發規範

程式設計

  1. 【必須】SQL必須指定列名操作,禁止用。COUNT()除外。
  2. 【必須】注意SQL的資料型別,where條件左右兩邊資料型別需一致,不一致時,強制轉換不走索引的那一端,以防出現隱式轉換,導致索引不可用
  3. 【必須】SQL中同一欄位OR條件改用IN(),IN包含的值少於50個
  4. 【必須】應用程式應有捕獲SQL異常的處理機制
  5. 【建議】需要走索引的條件,禁止在where 條件的過濾欄位使用函式或表示式處理。where ltrim(name)=’test’; where date_format(now(), '%Y-%m-%d')= '2018-01-01'
  6. 【建議】不使用負向查詢(NOT, <>)和%開頭的模糊查詢,如果需要走搜尋引擎來解決
  7. 【建議】避免使用子查詢
  8. 【建議】拒絕複雜SQL,將大的SQL拆分成多條簡單SQL
  9. 【建議】書寫格式統一縮排
  10. 【必須】使用表別名,SELECT列表中的列必須帶上表別名
  11. 【必須】事務要簡單,整個事務的時間長度不能太長
  12. 【必須】更新或刪除時,先寫SELECT語句,再改成update,delete語句
  13. 【必須】能用union all就不要用union,注意邏輯不一樣
  14. 【必須】禁止一個update同時更新多張表
  15. 【必須】對同一個表的多次DDL操作合併為一次操作
  16. 【建議】不建議使用子查詢,建議將子查詢轉換成JOIN查詢
  17. 【必須】不要使用 count(列名)或count(常量)來替代count(), count()是 SQL92 定義的.標準統計行數的語法,跟資料庫無關,跟 NULL 和非 NULL 無關
  18. 【注意】count(distinct col) 計算該列除 NULL 之外的不重複行數, 注意 count(distinct col1, col2) 如果其中一列全為 NULL,那麼即使另一列有不同的值,也返回為 0
  19. 【注意】當某一列的值全是 NULL 時, count(col)的返回結果為 0,但 sum(col)的返回結果為NULL,可以如下: SELECT IF(ISNULL(SUM(g)), 0, SUM(g)) FROM table_name;
  20. 【注意】NULL值與任何值比較結果都是NULL
  21. 【必須】線上程式中不建議使用truncate table語法。
  22. 【建議】不建議超過3張表的JOIN。
  23. 【建議】能序列處理SQL,批量序列處理,不使用多執行緒。
  24. 【建議】關係型資料庫適合批量處理資料,不建議一條一條處理資料。
  25. 【必須】只能使用inner/left/ JOIN … ON …寫法,不使用tableA,tableB where…寫法。
  26. 【必須】SQL即邏輯。

分頁查詢

  1. 【必須】精確分頁:計算記錄總條數與詳細記錄查詢分兩種SQL寫。因為計算總條數時,只用count(*),且可以不用關聯不必要的表。

  2. 【建議】精確分頁:詳細記錄查詢,先取出分頁記錄的id主鍵,再關聯其它。正例:

    select
     a.order_number,
     a.order_flag
    from sale_order a
    inner join
    (
     select id
     from sale_order
     where order_time > '2017-01-01'
     limit 100000, 20
    ) b
     on a.id=b.id
    
  3. 【建議】在程式碼中寫分頁查詢邏輯時,若 count 為 0 應直接返回,避免執行後面的分頁語句

效能規範

調優

  1. 在只讀伺服器(10.12.1.1)上使用explain調優SELECT語句,update&delete語句也可以改成select

故障

  1. 如果出現業務部門人為誤操作,需要恢復資料,請在第一時間通知 DBA,並提供準確時間點,誤操作語句,日誌等資訊。請提供日誌文字,不要截圖

DB運維規範

引數配置

  1. 必須使用InnoDB
  2. 符集必須使用UTF8或儲存emoji表情時使用UTF8MB4

複製

  1. 複製帳戶host限定為具體IP
  2. 複製master->slave的資料庫名必須相同,slave上覆制庫只能存放複製物件
  3. 複製資料庫必須同名,且slave上覆制庫中除了從master複製過來的物件,不能再有其它物件。


歡迎關注公眾號交流學習,會分享更多專案實踐以及學習資料: