1.總則
為規范公司各環境中數據庫系統的設計與創建流程,提高數據庫系統的開發效率,保障數據庫系統性能和安全穩定的運行,特制定本規范。
該規范涉及PM,RD,SQ,DBA四個角色,每個角色在數據庫系統設計與創建過程中的工作內容會按照【高危】、【強制】、【建議】三個級別進行標注,遵守優先級從高到低。
對于不符合【高?!亢汀緩娭啤績蓚€級別的工作內容,DBA會強制打回要求修改。
2.適用范圍
本規范所定義的數據庫系統包括部署在傳統數據中心(Cisco UCS 等物理機)和云(公有云、私有云)上的所有數據庫實例,相關數據庫實例參照相關規范進行數據庫開發與創建的工作。
3.PM需遵守的數據庫設計與創建規范
本規范旨在幫助或指導RD、QA、OP等技術人員做出適合線上業務的數據庫設計和開發。在數據庫變更和處理流程、數據庫表設計、SQL編寫等方面予以規范,從而為公司業務系統穩定、健康地運行提供保障。
3.1 MySQL設計開發規范
MySQL數據庫與 Oracle、 SQL Server 等商用數據庫相比,有其內核上的優勢與劣勢。我們在使用MySQL數據庫進行設計開發的時候需要遵循一定規范,揚長避短。
3.1.1 命名規范
數據庫對象的命名規則的范圍為管理平臺設計開發所涉及的表,對于其他外部系統所創建的表不在本規范約束范圍內,
數據庫對象如表、列、序列、過程、函數等在命名時要遵循如下規則:
【強制】命名要使用富有意義中英文縮寫,要以字母開頭,不能超過32個字符。
【強制】命名必須使用小寫字母,
【強制】數據庫對象名稱由如下部分組成:范圍、類型、名稱實體,各詞匯間采用下劃線“_”連接。
【強制】其中各數據庫對象的范圍和類型的具體含義及取值詳見各數據庫對象的命名規則。
數據庫對象命名規則
【強制】數據庫對象的名稱不允許是數據庫的 保留字 和 關鍵字。
SELECT id, name, from, age FROM user 不可以
保留字和關鍵字詳見連接
Option/Variable Reference
3.1.2 建庫規范
【強制】創建數據庫時必須顯式指定字符集,并且字符集只能是utf8或者utf8mb4。創建數據庫SQL舉例:
create database db1 default character set utf8;
3.1.3 建表規范
【強制】創建表時必須顯式指定字符集為utf8或utf8mb4。
【強制】創建表時必須顯式指定表存儲引擎類型,如無特殊需求,一律為InnoDB。當需要使用除InnoDB以外的存儲引擎時,必須通過DBA審核才能在生產環境中使用。因為Innodb表支持事務、行鎖、宕機恢復、MVCC等關系型數據庫重要特性,為業界使用最多的MySQL存儲引擎。而這是其他大多數存儲引擎不具備的,因此首推InnoDB。
【強制】建表必須有comment,從一開始就進行數據詞典的維護。類status型需指明主要值的含義,如”0-離線,1-在線”
【強制】中間表用于保留中間結果集,名稱必須以tmp_開頭。備份表用于備份或抓取源表快照,名稱必須以bak_開頭。中間表和備份表定期清理。
【強制】對于超過100W行的大表進行alter table,必須經過DBA審核,并在業務低峰期執行。因為alter table會產生表鎖,期間阻塞對于該表的所有寫入,對于業務可能會產生極大影響。
【建議】建表時關于主鍵:(1)強制要求主鍵為id,類型為int或bigint,且為auto_increment;(2)標識表里每一行主體的字段不要設為主鍵,建議設為其他字段如user_id,order_id等,并建立unique key索引。因為如果設為主鍵且主鍵值為隨機插入,則會導致innodb內部page分裂和大量隨機I/O,性能下降。
【建議】核心表(如用戶表,金錢相關的表)必須有行數據的創建時間字段create_time和最后更新時間字段update_time,便于查問題。
【建議】建議對表里的blob、text等大字段,垂直拆分到其他表里,僅在需要讀這些對象的時候才去select。
【建議】反范式設計:把經常需要join查詢的字段,在其他表里冗余一份。如user_name屬性在user_account,user_login_log等表里冗余一份,減少join查詢。
3.1.4 字段規范
【建議】表中所有字段必須都是NOT NULL屬性,業務可以根據需要定義DEFAULT值。因為使用NULL值會存在每一行都會占用額外存儲空間、數據遷移容易出錯、聚合函數計算結果偏差等問題。如果不能保證insert時一定有值過來,定義時使用default值 ‘ ’ 或 0。
使用NUMBER類型是必須指定長度。由NUMBER得到精度與密度來保障數據的一致性
表中字段的命名長度不應該超過30個字節
【建議】表中的自增列(auto_increment屬性),推薦使用bigint類型。因為無符號int存儲范圍為-2147483648~2147483647(大約21億左右),溢出后會導致報錯。
【建議】業務中選擇性很少的狀態status、類型type等字段推薦使用tinytint或者smallint類型節省存儲空間。
【建議】業務中IP地址字段推薦使用int類型,不推薦用char(15)。因為int只占4字節,可以用如下函數相互轉換,而char(15)占用至少15字節。一旦表數據行數到了1億,那么要多用1.1G存儲空間。
SQL:select inet_aton('192.168.2.12'); select inet_ntoa(3232236044);
php: ip2long(‘192.168.2.12’); long2ip(3530427185);
【建議】不推薦使用enum,set。 因為它們浪費空間,且枚舉值寫死了,變更不方便。推薦使用tinyint或smallint。
【建議】不推薦使用blob,text等類型。它們都比較浪費硬盤和內存空間。在加載表數據時,會讀取大字段到內存里從而浪費內存空間,影響系統性能。建議和PM、RD溝通,是否真的需要這么大字段。Innodb中當一行記錄超過8098字節時,會將該記錄中選取最長的一個字段將其768字節放在原始page里,該字段余下內容放在overflow-page里。不幸的是在compact行格式下,原始page和overflow-page都會加載。
【建議】存儲金錢的字段,建議用int,程序端乘以100和除以100進行存取。因為int占用4字節,而double占用8字節,空間浪費。
【建議】文本數據盡量用varchar存儲。因為varchar是變長存儲,比char更省空間。MySQL server層規定一行所有文本最多存65535字節,因此在utf8字符集下最多存21844個字符,超過會自動轉換為mediumtext字段。而text在utf8字符集下最多存21844個字符,mediumtext最多存2^24/3個字符,longtext最多存2^32個字符。一般建議用varchar類型,字符數不要超過2700。
【建議】時間類型盡量選取timestamp。因為datetime占用8字節,timestamp僅占用4字節,但是范圍為1970-01-01 00:00:01到2038-01-01 00:00:00。更為高階的方法,選用int來存儲時間,使用SQL函數unix_timestamp()和from_unixtime()來進行轉換。






