MySQL備份、安全、SQL規範與系統規劃
- 設定root密碼
- 移除匿名使用者
- 禁止遠端root登入
- 移除test資料庫
以上是5.6版本,5.7有所加強但也僅此而已,看看你的環境是否存在上述問題,這個算是最基本的安全吧。
2、連線訪問安全
常見建立使用者時你需要指定你的IP訪問地址範圍或者固定IP,一般而言,只有特定唯一的幾個IP才會訪問,或者說你可以採用代理訪問的方式,減少應用直接訪問你的資料庫,而且現在很多中介軟體也都有白名單機制,原則上是把非法請求防止在資料庫以外的地方。
規範資料庫管理軟體,實現管理軟體的標準、統一化,還有嚴禁杜絕開啟外網訪問,如果客戶端在遠端,就根本不應該直接訪問資料庫,而應該使用中介軟體堡壘機或其它替代方案。
為了防止連入資料庫的應用程式存在後門,造成資料庫安全隱患,檢查所有連線資料庫程式的安全性。通過使用堡壘機或者其它監控登入資料庫,禁止對資料庫的直接操作。
對已經連線的IP網段進行規範化、統一化的管理,定期進行許可權複核操作,對系統所屬IP、使用者進行許可權梳理工作。
對員工進行安全培訓,增強員工的系統安全觀念,做到細心操作,安全操作。確保訪問資料庫的主機為已知使用者或者主機,使用專門主機與資料庫進行連線。
對重要業務表的所有行為全部審計,審計同時所有包括即使是DBA的DDL操作行為。
3、許可權安全
許可權這塊無可厚非,在建立之初遵循最小許可權原則,堅持最小許可權原則,是資料庫安全的重要步驟。
以上說的是白話,下面說說正題。
很多時候我們不知道具體的最小許可權是什麼,你說一個賬號到底需要什麼樣許可權才合適,才不會影響業務?這個不是很好界定。我們需要知道在設定許可權時的資訊,要授予的許可權級別、庫級別、表級別、列級別,或者其它超級許可權、要授予的許可權型別,增刪改查等。
從mysql.user表來看
4、賬戶安全
使用者賬戶劃分原則:
- 超級管理員賬號
- 系統應用賬號(比如備份,監控,審計等)
- 應用業務賬號
- 業務人員賬號
- 開發人員賬號
- 測試人員賬號
- 其它專用賬號
主要是防止洩漏,非必要人員不需要知道賬號的名稱,同時需要制定相應的命名規則,還有就是合理使用自己的賬號密碼,保護好你的賬號密碼,對於絕無必要的使用者,先禁用,後期刪除,要做到無匿名賬戶和無廢棄賬戶。
5、目錄檔案安全
提高本地安全性,主要是防止MySQL對本地檔案的存取,會對系統構成威脅,還有Load DATA LOCAL INFILE,禁用該功能。
這個主要是防止誤刪除,非許可權使用者禁止訪問目錄,還有就是資料檔案禁止訪問,或者採用更改常用的目錄路徑,或者通過chroot,要保證該目錄不能讓未經授權的使用者訪問後把資料庫打包拷貝走了,所以要限制對該目錄的訪問。
6、密碼安全
- 密碼強度複雜性
儘量並且不要使用固定密碼,實行每個使用者單獨密碼,長度在16位以上 [email protected]#$%^&*()-+ 隨機組合。
- 密碼過期機制
根據公司的情況設定密碼過期時間,定期更改,同時不可使用重複密碼。
- 密碼儲存機制
為了方便管理,可能會採用一個密碼錶,要加強對於密碼錶的維護更新,最重要的是保證不洩漏。
7、漏洞安全
常規的方式是安裝補丁,不過這個往往比較麻煩,主要是版本升級,還有就是防護策略。
8、被忽視的SSL
由於效能或者其它方面原因,很多生產環境並沒有使用,不過從5.7+開始,已經好很多了,有需要的加強安全防範其實可以嘗試下了。
https://dev.mysql.com/doc/refman/5.7/en/mysql-ssl-rsa-setup.html
9、防火牆安全
一般化資料庫前面都會有主備的牆,不過從成本上考慮,很多企業都是單個或者裸奔的,有自己的硬體防火牆最好,沒有的話也可以使用系統自帶的防火牆,然後在加上其它白名單和中介軟體白名單過濾輔助措施,也能防止一部分問題。
10、埠安全
預設埠是3306,這個最好修改下,為了方便記憶,你可以根據的IP地址來加密動態調整,不過如果生產網路允許,也可以定期修改,最好不要影響研發進度。
11、記錄安全
刪除作業系統記錄的敏感資料,比如.mysql_history、.bash_history 等,及時清理,移除和禁用.mysql_history檔案。
人是安全的主導,管理的物件要從兩個角度來看,從資訊角度來說就是MySQL本身的安全,要防止資料的丟失和免遭破壞;從技術角度來說就是整個系統的安全,要防止系統的癱瘓和免遭破壞。
最後說句題外話,監控和審計,安全主要是防患於未然,沒有誰希望一天到晚接到各種警報,最好根據公司的實際情況訂個詳細的規章制度,不要覺得這個麻煩,有些你可能並不覺得有用,但是呢?我希望是沒有但是。
三、MySQL之SQL規範
不以規矩,不成方圓。
無可否認,很多時候由於專案的開發迭代過於頻繁,實時的需求反饋,可以及時調整產品的方向,不過由於各種大大小小的功能的耦合交錯,還有研發人員對資料庫的瞭解參差不齊,他們可能更加關注的是功能的實現,其次可能才是響應速度,這就導致了由於資料量小時看不出問題的SQL,一旦遇到大資料量,查詢效能或者說系統的響應速度會變慢,這是個值得關注的地方,為了防止出現這種情況,你需要做點什麼。
1、使用什麼
- 使用 InnoDB 儲存引擎,預設使用utf8mb4 字符集
- 使用自增主鍵,儘量每個表都有而且是非業務鍵值
- 使用合適的欄位型別,比如 VARCHAR 代替 CHAR 等,最好確定好長度
- 使用盡可能小的 VARCHAR 欄位
- 使用合適的 INTEGER、INT、SMALLINT、TINYINT、MEDIUMINT、 BIGINT 資料型別。https://dev.mysql.com/doc/refman/5.7/en/integer-types.html
- 使用 UNSIGNED 儲存非負數值,比如自增等
- 使用 INT UNSIGNED 儲存 IPV4 INET_ATON、INET_NTOA。更多 https://dev.mysql.com/doc/refman/5.7/en/miscellaneous-functions.html
- 必須使用 DECIMAL 代替 FLOAT 和 DOUBLE 儲存精確浮點數,比如與貨幣、金融相關的資料,防止運算丟失精度問題
- 使用註釋,所有表都需要添加註釋;除自增主鍵外的其他欄位都需要增加註釋
- 使用預設值,所有欄位都必須擁有預設值,不在表中儲存 NULL
- 使用 PREPARED STATEMENT,防止SQL注入
- 使用合理的 LIMIT 分頁方式以提高分頁效率
- 使用 EXISTS 適用於子查詢不返回實際資料,而表較大的情況,如果子查詢表較少可以考慮用in
- 使用 IN 代替 OR,同時 SQL 語句中IN包含的值不應過多,應少於1000個,否則使用轉為字串LIKE
- 使用 UNION ALL代替 UNION,減少不必要的去重消耗
- 使用 COUNT(1) 統計行數,如果使用欄位的話可能存在空值或NULL不準的情況
- 使用 INDEX,所有 WHERE 條件必須有索引,特別是 DELETE / UPDATE
- 使用 EXPLAIN EXTENDED 判斷SQL語句是否合理使用索引
- 使用 SHOW PROFILES 跟蹤資源使用
- 使用事務,增刪改必須有,程式應有捕獲SQL異常的處理機制
- 使用從庫,不是必要的查詢一律使用從庫查詢,減輕主庫壓力
2、減少什麼
- 減少不必要的固化查詢,合理使用 Memcached、Redis、MongoDB等
- 減少不需要的空連線,及時關閉
- 減少不必要的連線,儘量採用批量SQL語句
- 減少不必要的大事務,儘量做拆分
- 減少查詢的資料量,大量查詢分批次
- 減少遊標和臨時表的使用,如果有的話
3、避免什麼
- 避免使用TEXT、BLOB型別等
- 避免向客戶端返回大資料量,若資料量過大,應該考慮相應需求是否合理
- 避免使用子查詢 IN ,必要時使用JOIN。
- 避免出現NOW()、RAND()、SYSDATE()、CURRENT_USER()等不確定結果的函式
- 避免在索引列上使用IS NULL和IS NOT NULL
- 避免同一個表上索引過多,重複索引,太多的索引可能提高了查詢效率,但是也增加了增刪改的開銷
4、禁止什麼
- 禁止在資料庫中儲存圖片、檔案等大資料
- 禁止使用order by rand(),類似的有很多替代方案
- 禁止使用SELECT *,根據需要獲取相對應需要的欄位
- 禁止使用預留欄位,無論從流程和規範上都說不過去
- 禁止在MySQL中進行數學運算和函式運算
- 禁止隱式轉換,數值型別禁止加引號,字串型別必須加引號
- 禁止使用 INSERT INTO TABLE(),需要指定相應的欄位,最好是順序的
- 禁止使用前置百分號,例如:WHERE A LIKE ‘%B’
- 禁止使用 NOT 查詢,例如 NOT IN、!=、NOT LIKE
- 禁止單條SQL語句同時更新多個表
- 禁止使用儲存過程、觸發器、檢視、自定義函式等
- 禁止在從庫上執行負責統計類查詢,使用專用從庫
- 禁止在資料庫中儲存明文密碼
5、注意什麼
- 合併對於單表多次的操作
- 表結構變更必須通知DBA稽核參與
- 重要專案的資料庫方案選型和設計必須提前通知DBA參與
- 禁止在線上做資料庫壓力測試
- 禁止從測試、開發環境直連線上資料庫
- 禁止有超級許可權的應用程式賬號存在
- 禁止有DDL、DCL許可權的應用程式賬號存在
- 批量匯入、匯出資料必須通過DBA稽核,並在執行過程中觀察服務
- 批量更新資料,如UPDATE、DELETE操作,必須DBA進行稽核,並在執行過程中觀察服務
- 產品出現非資料庫導致的故障時,如被攻擊,必須及時通DBA,便於維護服務穩定
- 業務部門程式出現BUG等影響資料庫服務的問題,必須及時通知DBA,便於維護服務穩定
- 業務部門推廣活動或上線新功能,必須提前通知DBA進行服務和訪問量評估,並留出必要時間以便DBA完成擴容
- 出現業務部門人為誤操作導致資料丟失,需要恢復資料的,必須第一時間通知DBA,並提供準確時間點、 誤操作語句等重要線索
- 提交線上建表改表需求,必須詳細註明涉及到的所有SQL語句(包括INSERT、DELETE、UPDATE),便於DBA進⾏行稽核和優化
以上相對比較常規,一個完善合理的規範當然還需要一個比較長的過程。
四、MySQL之系統規劃
1、環境規劃
MySQL作為流行的開源資料庫擁有多個重要分支,每個分支都有各自的優缺點,這裡不做過多評價,總的來說,MySQL仍然是一款非常出色的產品,是一個非常適合大多數場景下使用的資料庫,無論是從可用性、可擴充套件性、效能和管理各方面都是不錯的選擇。
當然說為了追求某些方面的新的功能性需求,或者MySQL版本覺得太臃腫,你也可以嘗試其他版本,主要是符合你的業務場景才是最合適的。
根據研發的階段來劃分主要分為開發階段、測試階段、準生產階段、壓測階段、上線階段。
- 開發階段-開發環境
資料庫和系統的版本可能都比較新,這裡面有一部分是嚐鮮的概念在裡面,同時,也為了以後的版本更新提供了一定的基礎,其次是研發人員對於資料庫和作業系統的許可權是比較大的,基本上會all in,主要保證開發的進度。
- 測試階段-測試環境
這個環境的版本可能也是比較新的,不過已經很貼近生產了,然後是對於許可權的話,由於主要是測試階段,研發人員和測試人員的許可權基本上限定到庫表的DML許可權,很難執行其它特別是DDL操作了,當然還是以保證開發和測試為主。
- 準生產階段-準生產環境
原則上這個環境跟生產環境基本上1:1,版本跟生產是一樣的,其次配置比生產會低很多,許可權的話,已經不允許DDL語句了,並且DML也會嚴格控制。
- 壓測階段–壓測環境
一般化而言,很多公司會把準這個壓測環境放到準生產上面,對此,我不反對不建議,完全看你的想法和公司的規劃,壓測環境跟生產環境保證100%完全一致性,因為為了追求那個極致,同時全面禁止的DDL,只讀環境。
PS:很多時候,你的準生產可能就是壓測環境,這邊就不做過多說明了,主要還是看你的規劃。
- 上線階段–線上環境
這個就不說了,完全禁止的DML、DDL操作,任何操作必須有記錄,比如審計、工單等等。
2、容量規劃
容量規劃主要是如何有效評估需求,如果說沒有統一綜合的管理機制,各種專案的資源申請各自為政,沒有考慮到綜合實際使用的資源情況,會造成嚴重的分配問題,或者說資源不足,有可能部分專案的提前預支超過實際情況的資源,其它專案完全沒有資源,或者專案資源是有時間期限的,過了期限就需要即使的回收利用。
對於資料庫本身容量規劃更加重要,畢竟你的資料都在裡面,首先專案初始階段可能會預估下使用量,然後還需要定期的實際評估,根據資源的使用情況及時調整,綜合規劃各個專案的資源配置。
MySQL的容量規劃主要是庫表的大小,這個主要是看業務量,很多時候業務部門會說我的計劃目標是1kw使用者量,那麼可能很難有一個估計的大小,因為你的庫表一直是在變化的,自然而言,比較困難評估一個大概的容量,而且如果資料量太大的情況下,從資料的訪問響應速度就需要考慮分庫分表了,這個主要還是看的業務場景和需要的響應速度。
3、檔案規劃
MySQL資料檔案目錄還是比較簡單的,可以分成資料檔案目錄、日誌檔案目錄、引數檔案目錄、其它檔案目錄等。
- 資料檔案目錄
資料檔案主要按照庫表單位劃分的,由於引擎的不同可能分成結構定義檔案、資料檔案、索引檔案。
- 日誌檔案目錄
這裡麵包括了啟動日誌、報錯日誌、查詢日誌、慢查詢日誌、binlog日誌、binlog索引檔案、relay_log中繼日誌、relay_log中繼日誌索引檔案等。
- 引數檔案目錄
包括pid、sock、cnf 檔案等。
- 其他檔案目錄
包括redo、undo、ibdata1、ibtmp1檔案等。
歸檔,這邊說的歸檔規劃是定期把以上各類檔案備份歸檔,資料檔案自不必說,其它檔案也是需要定期歸檔的,歸檔的方法有很多,你可以把相應的檔案根據不同的規律存放在結構化或者非結構化的地方。
4、審計規劃
資料庫審計能夠實時記錄網路上的資料庫活動,對資料庫操作進行細粒度審計的合規性管理,對資料庫遭受到的風險行為進行告警,對攻擊行為進行阻斷。
它通過對使用者訪問資料庫行為的記錄、分析和彙報,用來幫助使用者事後生成合規報告、事故追根溯源,同時加強內外部資料庫網路行為記錄,提高資料安全。
審計對資料庫記錄和行為進行獨立的審查和估計,其主要作用和目的包括以下幾個方面:
- 對可能存在的潛在攻擊者起到威懾和警示作用,核心是風險評估。
- 測試系統的控制情況,及時進行調整,保證與安全策略和操作規程協調一致。
- 對已出現的破壞事件,做出評估並提供有效的災難恢復和追究責任的依據。
- 對系統控制、安全策略與規程中的變更進行評價和反饋,以便修訂決策和部署。
- 協助系統管理員及時發現網路系統入侵或潛在的系統漏洞及隱患。
有個不知道算奇怪還是正常的事情,不知道多少人給生產恢復過資料,這裡面不談因由,只有做過的人才知道這其中的坑有多少,所以也就需要大家對於各種恢復手段都有所瞭解,乃至於熟練掌握。
雖然防患未然還是比較困難,畢竟各種情況都會發生,但至少可以未雨綢繆,從安全上講,有了審計就可以大大減少這類事情的發生。
對於資料庫而言,無論是硬體裝置還是軟體審計都會加大資料庫的壓力,從效能的損耗上講,事後審計是比較折中的策略,這邊先講下軟體部分的,無論是MySQL官方還是MariaDB或者Percona還是其它的都有一套自己的審計產品。
下面列下常用的幾種:
- MariaDB Audit Plugin(https://mariadb.com/kb/en/mariadb/about-the-mariadb-audit-plugin/),
- Percona(https://www.percona.com/doc/percona-server/5.6/management/audit_log_plugin.html),
- MySQL(https://dev.mysql.com/doc/refman/5.7/en/audit-log.html),
mcafee(https://github.com/mcafee/mysql-audit)
主要用哪個還得看你適合哪個,如果你有足夠的資源可以考慮採用硬體的模式,儘量選擇專門審計裝置的裝置,然後根據定期的報表檢查你的相關配置。
前面列出的幾個感興趣的小夥伴可以具體測試下,當然如果你已經在使用了,那我們可以私下交流。
5、備份恢復規劃
備份和恢復是兩個相互關聯的,至於備份恢復的種種前面已經有說過了,關於備份恢復也有一系列的軟硬體,這邊主要說下規劃。
你首選要根據自己的實際情況做需求分析,你需要有當前使用資料庫的型別、版本資訊、配置資訊、資料量總大小、每日新增大小、備份方式(物理備份/邏輯備份)、業務高峰期,當然還有資料庫的主機的系統情況等資訊。
備份策略,根據不同的業務還有其它需要確定,常用的是全量、增量、差異備份三種,實際情況下很多都是三種策略的結合使用。
備份大小,這個取決於你採用的備份方式,會有一個大致的增長值,這個可能需要跟業務那邊的規劃做詳細的統計,給出一個大概的範圍。
備份保留時間,這個跟備份的大小、備份介質的大小、價效比有關係。
如果你的介質空間太小,自然而然也就不能保留太長時間,這個時候,通常會根據業務的核心程度來劃分,應確定重要業務備份的儲存期以及其它需要永久儲存的備份,總的來說,保留半年之類的有效資料是基本的要求。
備份介質大小,根據你的保留時間合理地規劃你的備份介質大小。
備份計劃,這個跟恢復策略有關係,基本上是你需要一個專門備份的資料庫,這個主要是為了減少對主庫的影響,對此大部分是資料庫都支援該方案,當然主庫執行備份也不是不可以,只要合理使用。
根據業務繁忙的情況,在合理的時間和空間下能全備的儘量全備,雖然全量可能會增加資料的重複性和空間的使用,你可以適當加上增量或者差異備份。
太大的庫可能全備時間太長,優化過後還是不能接受,可以選擇一個相對不繁忙的時間做全量備份,然後加上增量或者差異備份,當然這個全量的頻率還是需要根據你的業務來結合。總不能說,我需要恢復昨天的資料,你告訴我只有上上上個月的全備加上增量或者差異,這個恢復的時間一般會比較長,這個肯定不能滿足的需求,所以備份計劃要完全貼合你的業務需求,以及需要詳細指定最大容忍的時間性要求。
備份執行過程應有詳細的規劃和記錄,包括備份重要等級、備份主體、備份時間、備份策略、備份路徑、記錄介質(型別)等。
同時備份檔案加密許可權控制也是不可或缺的,所有操作需要保留相應記錄,方便審計跟蹤,安全需要時刻關注。
恢復規劃,這個不能說是規劃,我覺得這個應該更像一個日常的計劃任務,如果你有充足的資源,特別的恢復伺服器組,我希望你在每天完成備份並且上傳統一的備份介質後,每天都可以把所有的系統都恢復一次,不要覺得太麻煩,有時候這些麻煩會幫你很多,當你把所有的一切做成定時任務之後,你會發現,生活太美好。
實際的情況往往比這個更加複雜,我們把容災劃分成很多的等級,計算機軟體故障、人為原因、計劃性停機,然後從等級上是時間上有幾個九,同時還有災備的環境一些措施,確保可以在規定的時間內完成有效性恢復。
但是,當災難發生的時候,很多東西都會很巧合地併發發生,會很亂,假使災備環境也不是正常的或者壓根就沒有所謂的災備環境,那個時候你依賴的可能也僅僅是備份的一個有效恢復,那個時候,壓力會稍微有點大,如果你對恢復情況不是很瞭解,或者不是很熟練,我們也只能就這麼看著能恢復多少,心裡沒有底,這個時候才會覺得恢復測試真的非常重要。
平時我們關注的大都在日常的備份上,並不會實際去驗證,不過其實日常恢復演練更加重要,即使不能做到所有系統的恢復計劃,起碼保證核心系統的備份的有效性,同時制定恢復測試計劃。
總結
總之,對於資料庫而言,首先要求我們擁有一個完整的備份,有了備份你才能做很多事,同時也會省了很多事。其次是安全,無論是資料備份的安全還是資料本身或者研發使用中的安全,都值得關注。然後是資料庫本身的使用,合情合理的使用。最後對於你所維護的資料庫你需要擁有詳細的規劃,無論是管理角度還是使用角度都需要。
最後給大家提幾點建議:
- 未雨綢繆,不要停留在制度上,而是實際做出來。
- 亡羊補牢,舉一反三,切記,不能好了傷疤忘了疼。
- 完備的架構設計及備份,恢復策略及備份驗證策略。
- 定期思考,並實戰模擬以上策略演練。
- 實踐是檢驗真理的唯一標準。
文章來自微信公眾號:DBAplus社群