1. 程式人生 > >一張思維導圖縱觀MySQL資料安全體系

一張思維導圖縱觀MySQL資料安全體系

作者介紹 :
楊奇龍,前阿里資料庫團隊資深DBA,主要負責淘寶業務線,經歷多次雙十一,有海量業務訪問DB架構設計經驗。目前就職於有贊科技,負責資料庫運維工作,熟悉MySQL效能優化、故障診斷、效能壓測。

簡介

和團隊內部的同事一起溝通,討論了MySQL資料庫系統資料安全性問題,主要針對MySQL丟資料 、主從不一致的場景 ,還有業務層面使用不得當導致主備庫資料結構不一樣的情況,本文是基於以上的討論和總結做的思維導圖。

思維導圖

內容展示

OS

  • BBU:資料庫伺服器要配置BBU,BBU在電源供應出現問題的時候,為RAID控制器快取提供電源。當電源斷電時,BBU電力可以使控制器內快取中的資料可以儲存一定時間(根據BBU的型號而決定)。使用者只需要在BBU電力耗盡之前恢復正常供電,快取中的資料即可被完整的寫回RAID中,避免斷電導致資料丟失
  • 防止OS異常斷電導致資料無法正常落盤
  • 磁碟禁用cache,MySQL的 O_DIRECT 方式可以跳過pagecache寫資料

單機

(1)redo log

innodb_flush_log_at_timeout

< 5.6.6: 每隔一秒將redo log buffer中的資料重新整理到磁碟

>= 5.6.6:每隔innodb_flush_log_at_timeout秒將資料重新整理到磁碟中去

(2)binlog

sync_binlog  =1

(3)innodb buffer data

不同的flush mathod刷資料的圖形展示。圖片來自hatemysql.com。

(4)InnoDB 落盤

MySQL資料落盤的路徑,圖片來自李春hatemysql.com。

主從不一致

  • 主庫insert之後再回滾 ,主備庫自增主鍵不一致
  • 使用replace into操作,導致主備庫自增主鍵不一致
  • set session sql_log_bin=0

業務架構

常見的雙寫

“丟”資料的場景

(1)slave_skip_counter 不合理

slave_skip_counter =1
slave_skip_counter >1

(2)DB Crash,OS正常

innodb_flush_log_at_trx_commit=0
事務提交時,不重新整理快取,系統重新整理的頻率是1s,故會丟失1s的資料。

innodb_flush_log_at_trx_commit=1
事務提交時,會重新整理到磁碟,保證事務落盤,故不丟資料。

innodb_flush_log_at_trx_commit=2
事務提交時,重新整理到os cache,系統沒有crash,資料無丟失。

(3)DB正常,OS Crash

帶有 BBU

innodb_flush_log_at_trx_commit=0
事務提交時,不重新整理快取,系統重新整理的頻率是1s,故會丟失1s的資料。

innodb_flush_log_at_trx_commit=1
事務提交時,會重新整理到磁碟,保證事務落盤,故不丟資料。

innodb_flush_log_at_trx_commit=2
事務提交時,重新整理到os cache,系統沒有crash,資料無丟失。

(4)slave非實時寫redo和binlog丟失資料

在slave機器上會存在三個檔案來保證事件的正確重放:relay log、 relay log info、 master info。

(5)非同步模式

  • 事務T1寫入binlog buffer;
  • dumper執行緒通知slave有新的事務T1;
  • binlog buffer進行checkpoint;
  • slave因為網路不穩定,一直沒有收到t1;master掛掉,slave提升為新的master,t1丟失。

(6)semi sysnc

after_commit

比如主庫操作update t1 set val=1 where id=10將val從5修改為1 。

  1. 會話session1在主庫提交update t1 set val=1 where id=10 ;commit;
  2. 主庫根據二階段提交將資料持久化到innodb和提交日誌binlog;
  3. 同步日誌到slave ,並等待slave 返回ack資訊,等待的實際時間以 rpl_semi_sync_master_timeout 為準,超過該設定時間則超時,主庫返回給客戶端成功寫入資訊。
  4. 接收到來自slave的ack資訊,返回成功給OK客戶端。

分析:

  • 第四步之前,master還未收到slave的ack資訊,此時由於事務已經提交,除了session1,其他會話是可以看到 val=1。
  • 主庫伺服器down或者主庫例項crash,此時發生HA切換。
  • 主庫未接收到slave的ack資訊,slave接收到日誌並落盤,應用binlog更新。t1.val=1,此時業務切換到slave上能獲取到一致的資料。
  • 如果在slave還未接收到binlog並且主庫掛了,因為主庫已經提交,此時主庫t1.val是1而從庫t1.val是5,主備不一致。

    after_sync

    比如主庫操作update t1 set val=1 where id=10將val從5修改為1。

    1. 會話session1在主庫提交 :update t1 set val=1 where id=10;commit;
    2. 主庫將事務寫入binlog。
    3. 將binlog同步給slave,不提交。
    4. 等待slave返回ack資訊,等待的實際時間以rpl_semi_sync_master_timeout為準,如果超時master改為非同步模式。
    5. 接收到來自slave的ack資訊,主庫進行提交併且返回成功給OK客戶端。

    分析:

    • 如果在第3步等待slave ack的過程中,主庫發生crash(此時t1.val=5),HA 切換到slave,應用查詢slave 。如果slave接收到binlog併發送ack給master,則t1.val=1。
    • 如果slave響應主庫,但是主庫crash ,此時因為主庫還沒提交t1.val=1, slave t1.val=5,但是主庫啟動恢復之後t1.val會變成5,主備還是一致的。
    • 如果slave未接收到事務和響應主庫,此時t1.val=5,無論哪種狀態,對於所有客戶端資料庫都是一致,事務都沒有丟失。

      知識點:兩階段提交

      第一階段是先prepare、再同步寫redo log,第二階段同步寫binlog、再commit,如果在寫入commit標誌時崩潰,則恢復時,會重新對commit標誌進行寫入。

      HA切換

      (6)主從

      binlog_format

      ROW(最安全)
      MIXED(不推薦)
      STATEMENT(不推薦)

      sync_binlog

      =0:由os系統的重新整理機制來控制,重新整理資料到磁碟的頻率
      =1:每次commit重新整理到磁碟
      >1:每N次提交重新整理到磁碟

      innodb_support_xa

      版本要開啟,保證binlog提交的順序,否則亂序的binlog在恢復或者slave應用的時候會有問題,及以後廢棄,始終支援兩階段提交。

      crash safe

      crash-safe就是將relay-info.log的資訊儲存在InnoDB的事務表中,這時執行relay log中的事務和寫relay info在一個事務中,就能得到原子性保證。從而避免已執行的binlog位點和寫入relay log info的位點資訊不一致的情況發生。

      IO thread

      master-info-repository=TABLE
      sync_master_info=N:每N個event重新整理一次表

      SQL thread

      relay-log-info-repository=TABLE
      sync_relay_info=N:每N個event重新整理一次表

      relay-log-recovery

      當slave從庫宕機後,假如relay-log損壞了,導致一部分中繼日誌沒有處理,則自動放棄所有未執行的relay-log,並且重新從master上獲取日誌,這樣就保證了relay-log的完整性。

      relay_log_info_repository = TABLE
      relay_log_recovery = 1

      http://mysqlserverteam.com/relay-log-recovery-when-sql-threads-position-is-unavailable/

      semi_sync

      • after commit:master把每一個事務寫到二進位制日誌並儲存到磁碟上,並且提交(commit)事務,再把事務傳送給從庫,開始等待slave的應答。響應後master返回結果給客戶端,客戶端才可繼續。
      • after sync:master把每一個事務寫到二進位制日誌並儲存磁碟上,並且把事務傳送給從庫,開始等待slave的應答。確認slave響應後,再提交(commit)事務到儲存引擎,並返回結果給客戶端,客戶端才可繼續。

      GTID

      相比位點複製,能減少不一致的概率

      參考資料

      • MySQL資料丟失討論http://hatemysql.com/?p=395
      • 細看InnoDB資料落盤http://hatemysql.com/?p=503
      • MySQL5.7 深度解析:Loss-Less半同步複製技術
      • MySQL 5.7 Replication相關新功能說明

      原文來自微信公眾號:DBAplus社群