天天看點

關閉删庫跑路的後門,打造高可用的MySQL(下)2 最佳實踐3 打造高可用的MySQL

1.2.1.3 檢視狀态

  • show master status
  • 關閉删庫跑路的後門,打造高可用的MySQL(下)2 最佳實踐3 打造高可用的MySQL
  • 顯示正在寫入的Binlog檔案,及目前的位置。

    假設我們每天淩晨用mysqldump做一個全量備份,然後開啟了Binlog,有了這些,就可以把資料恢複到全量備份之後的任一時刻。

用Binlog把資料恢複到删庫跑路之前的那個時刻:

$mysqlbinlog --start-datetime "2020-05-16 00:00:00" 
--stop-datetime "2020-05-16 18:00:00" 
/usr/local/var/mysql/binlog.000001 | mysql -uroot      

這時候,資料已經恢複到當天的18點了。

定期的全量備份 + Binlog,就可以把資料恢複到任一曆史時間點。

2 最佳實踐

無論全量備份還是Binlog,都不要和資料庫存放在同一伺服器

在回放Binlog時,指定的起始時間可以比全量備份的時間稍微提前,確定全量備份之後的所有操作都在恢複的Binlog範圍内,保證恢複的資料的完整性。

因為回放Binlog操作是幂等的(需要設定Binlog為ROW格式),是以重複回放的那部分Binlog并不會影響資料的準确性。

3 打造高可用的MySQL

恢複資料時間很長,這期間系統一直不可用,怎麼搞?

不要等着資料庫當機,才開始做恢複,平時就要恢複。

3.1 異步複制

一主一從,性能佳。

實時地在主備資料庫之間來同步Binlog,主庫做了一次資料變更,生成一條Binlog,我們就把這一條Binlog複制到備用庫并立即回放,這樣就可以讓備用庫裡面的資料和主庫中的資料一直保持是一樣的。一旦主庫當機,就可以立即切換到備用庫上繼續提供服務。

MySQL本身提供了主從複制

https://dev.mysql.com/doc/refman/8.0/en/replication.html

方案的問題。當我們對主庫執行一次更新操作的時候,主從兩個資料庫更新資料實際的時序是這樣的:

在主庫的磁盤上寫入Binlog

主庫更新存儲引擎中的資料

給用戶端傳回成功響應

主庫把Binlog複制到從庫

從庫回放Binlog,更新存儲引擎中的資料。

主從延遲

從庫的資料有可能比主庫上的資料舊。

正常情況下,主從延遲基本都是毫秒級别,可認為就是實時保持同步。

不正常的,一旦主庫或者從庫繁忙的時候,會出現明顯的主從延遲。

很多情況下,資料庫都不是突然當機的,而是先繁忙,性能下降,最終當機。這種情況下,很有可能主從延遲很大,如果我們把業務直接切到從庫上繼續讀寫,主從延遲這部分資料就丢了,并且這個資料丢失是不可逆的。即使事後你找回了當時主庫的Binlog也是沒法做到自動恢複的,因為它和從庫的資料是沖突的。

簡單地說,如果主庫當機并且主從存在延遲的情況下,切換到從庫繼續讀寫,可以保證業務的可用性,但是主從延遲這部分資料就丢失了。

這個時候你就需要做一個選擇題了

保證不丢資料,犧牲可用性,暫時停止服務,想辦法把主庫的Binlog恢複到從庫上之後再提供服務

冒着丢一些資料的風險,保證可用性,第一時間切換到從庫繼續提供服務

能不能既保證資料不丢,還高可用?

3.2 同步複制

自動切換,性能最差。

MySQL支援

同步複制

,開啟同步複制時,MySQL主庫會等待資料成功複制到從庫之後,再給用戶端傳回響應。

一主一從的隐患

從庫當機了怎麼辦?本來從庫當機對主庫是完全沒影響的,因為現在主庫要等待從庫寫入成功再傳回,從庫當機,主庫就會一直等待從庫,主庫也卡死了。

一主雙從

得加一個從庫,主庫配置成:成功複制到任意一個從庫就傳回,隻要有一個從庫還活着,就不會影響主庫寫入資料,這樣就解決了從庫當機阻塞主庫的問題。

如果主庫發生當機,在兩個從庫中,至少有一個從庫中的資料是和主庫完全一樣的,可以把這個庫作為新的主庫,繼續提供服務。

代價

至少用三台資料庫伺服器,但這三台的服務性能,還不如一台。