刪庫跑路後真的沒有辦法彌補了嗎?

提出問題?

  1. 服務器數據庫異常重啓了會形成什麼樣的影響?
  2. 不當心刪除了數據庫怎麼辦,或者不當心刪除了數據庫表中數據怎麼辦?
  3. 一條更新語句在數據庫系統內部執行時與數據庫日誌系統有什麼聯繫?
  4. 數據庫備份,是天天一備比較好,仍是每週一備比較好? 接下來在講解日誌系統的同時,回答上面的幾個問題。

日誌系統詳解:

redo日誌(重作日誌)

redo是引擎層的日誌,並且是InnoDB特有的。InnoDB的redo log是有固定大小的,好比能夠配置爲 一組4個文件(logfile-1,logfile-2,logfile-3,logfile-4),每一個文件的大小是1GB,那麼它總共能夠記錄4GB的操做。一個環狀循環結構,從頭開始寫,寫到末尾又回到開始循環寫。mysql

redo中的環狀結構

結構圖:sql

write pos是當前記錄的位置,一邊寫一邊後移,環狀結構,寫到3號文件末尾就會回到0號文件開頭。checkpoint是當前擦除的位置,也是日後推移而且循環的。注意擦除記錄前要把記錄更新到數據文件(這裏能夠聯想 粉板 老闆正式記帳本的例子)

redo日誌做用(回答提出問題1)

  1. 在MySQL中,若是每一次的更新操做都寫進磁盤,而後磁盤也找到對應的那條記錄,而後再更新,整個過程io成本,查找成本都很高,爲了解決這個問題,提高效率,就會用到redo日誌,MySQL常常說的的WAL技術,WAL的全稱是write-Ahead-Logging,它的關鍵點就是先寫日誌,再寫磁盤。具體說,當有一條記錄須要更新的時候,InoDB引擎會先記錄到redo log,並更新內存,這時候更新就算完成了。同時InnoDb引擎會在適當的時候,將這個操做記錄更新到磁盤裏面,而這個更新每每是在系統比較空閒的時候作。
  2. 正是由於有了redo log ,InnoDB就能夠保證即便數據庫發生異常重啓,以前提交的記錄多不會消失,這個能力叫crash-safe。只要數據庫的物理記錄還在redo log中,就是服務器數據庫出現問題重啓,數據庫恢復後,數據記錄仍然能夠恢復。

binlog日誌(歸檔日誌)

Mysql基礎架構總體分爲兩部分:Server層和引擎層,引擎層主要負責存儲相關的事宜。上面說到在引擎層有本身的日誌,並且只在InnoDB引擎中才有。Server層也有本身的日誌,稱爲binlog(歸檔日誌)。它是採用追寫入日誌的方式。追加寫是指binlog文件寫到必定大小後會切換到下一個,並不會覆蓋之前的日誌。數據庫

binlog日誌做用(回答提出問題2)

只依靠redo日誌的crash-safe特性在應對數據庫誤刪,表數據誤刪等操做時候,有些時候redo日誌是無力的,可是binlog日誌解決這些問題,由於binlog會記錄全部的邏輯操做,而且採用「追加寫」的形式。bash

舉個例子若是公司員工發現某天下午有一個誤刪表數據操做,要求找回數據,應該怎麼作?(注:這裏要考慮是在剛備份以後誤刪除,仍是備份以前誤刪除,下面的例子是在備份以前刪除的,找以前刪除的數據)服務器

  1. 首先,找到最近的一次全量備份,這要看大家公司的數據庫是多久備份一次(有的公司是一天,有的公司是一週,並且會按期刪除,不少公司只保留最近一個月的數據庫備份),拿到備份數據後,把這個備份數據恢復到臨時表
  2. 而後從備份的時間點開始,將備份的binlog依次取出來,重放到誤刪表以前的那個時刻
  3. 這時候臨時庫跟誤刪以前的線上庫同樣了,而後把表數據從臨時數據取出來,按需恢復到線上庫去。

redo日誌與binlog日誌對比

redo日誌與binlog日誌有哪些不一樣? 其實上面好多都提到過,再次總結一遍,加深印象。架構

  1. redo log是InnoDB引擎特有的;binlog是MySQL的Server層實現的,全部的引擎均可以使用。
  2. redo log是物理日誌,記錄的是某個數據頁上作了什麼修改;binlog是邏輯日誌,記錄的是這個語句的原始邏輯,好比「給ID=2這一行的c字段加一」
  3. redo log是環狀結構,循環寫,空間固定會用完,用完後須要擦除;binlog是能夠追加寫入的。「追加寫」是隻belog文件寫到必定大小後會切換到下一個,並不會覆蓋之前的日誌。

更新語句執行流程(與日誌關係)

數據庫語句:學習

mysql> update Student set c=c+1 where ID=2;

複製代碼

經過分析這一條更新語句,畫出流程圖,問題3也就獲得解決。ui

注意流程圖的最後三步,這是更新語句和日誌關係密切的地方,將redo日誌拆成了兩個步驟:prepare和commit,它倆的中間是執行器寫入binlog。(注:若是不這麼作,假如一個日誌提交成功的時候,另外一個日誌提交以前發生了數據庫發生了崩潰,可是crash-safe恢復或者誤刪庫恢復的時候可能形成兩者數據不統一出現問題。)

開發過程當中如何爲mysql設置這兩種保存日誌的配置

  • redo logspa

    innodb_flush_log_at_trx_commit 這個參數設置成 1 的時候,表示每次事務的 redo log 都直接持久化到磁盤。這個參數我建議你設置成 1,這樣能夠保證 MySQL 異常重啓以後數據不丟失。3d

  • binlog

    sync_binlog 這個參數設置成 1 的時候,表示每次事務的 binlog 都持久化到磁盤。這個參數我也建議你設置成 1,這樣能夠保證 MySQL 誤刪除操做(刪除表數據,刪除庫數據) 經過binlog 仍可恢復。

如何查看這兩種日誌

關於日誌系統的一些誤區和疑問

  • 你們會不會想有了redo日誌就能夠了,爲何還要出現binlog日誌呢?

    解答:

    1. redo日誌是隻要InnoDB引擎才提供的一個內容。
    2. redo日誌是環狀結構循環寫入,而且到了配置的固定大小後會被擦除,誤刪除數據庫或表數據的時候,備份可能會出現沒法所有還原。
  • 這裏有一個問題:若是在擦除和記帳重合那一刻,數據庫異常重啓了,新的數據庫操做會怎麼記錄,是擦除一部分,記錄上,會丟失,仍是等待重啓後往上添加數據?

  • 關於數據庫備份,是一天一備比較好,仍是一週一備份比較好,通常備份文件保留多久?提出問題4解決

    解答:對於數據庫備份週期這個問題,須要考慮如下指標:數據存量、增量、備份成本、恢復效率。

    1. 若是數據存量大到一天都無法備份完成,只能一週一次甚至更長時間
    2. 業務數據的增量,若是增量很是大,若是一週備份一次,可能會出現增量備份失敗問題,並且恢復時長和成功率也比較困難,則能夠考慮一日一備。
    3. 業務比較重要,且對恢復時間的忍耐程度低,以前屢次發生過數據回滾的需求,數據增量還不小,能夠考慮一天一備。相反業務實際不重要,出問題能夠容忍必定的不可用,增量還很少,能夠考慮一週一備份。

    總的來講就是和項目,需求,場景有不少關係。

  • 寫入redo日誌也是io操做,數據更新直接寫入磁盤也是io操做,爲何說寫入redo日誌效率高節省io成本呢?

    解答:redo日誌的寫入是順序寫入的,不用去「找位置」,而直接更新數據到磁盤的話,須要到磁盤中找到位置再寫入,確定前者的效率高。

總結與宣傳

以上內容是關於數據庫日誌系統的講解,同時解決了我開篇提出的幾個數據庫日誌相關的問題,但願能幫助你們更好的瞭解學習數據庫,若是有問題能夠隨時關注公衆號聯繫,互相學習哦。

相關文章
相關標籤/搜索