摘要:問題原因非正常關(guān)機(jī)導(dǎo)致沒有把數(shù)據(jù)及時的寫入硬盤。丟失的臨時表臨時表和基于語句的復(fù)制方式不相容。如果備庫崩潰或者正常關(guān)閉,任何復(fù)制線程擁有的臨時表都會丟失。臨時表的特性只對創(chuàng)建臨時表的連接可見。
主備復(fù)制過程中有很大可能會出現(xiàn)各種問題,接下來我們就討論一些比較普遍的問題,以及當(dāng)遇到這些問題時,如何解決或者預(yù)防問題發(fā)生。
1 數(shù)據(jù)損壞或丟失問題描述:服務(wù)器崩潰、斷電、磁盤損壞、內(nèi)存或網(wǎng)絡(luò)錯誤等問題,導(dǎo)致數(shù)據(jù)損壞或丟失。
問題原因:非正常關(guān)機(jī)導(dǎo)致沒有把數(shù)據(jù)及時的寫入硬盤。
這種問題,一般可以分為幾種情況導(dǎo)致:
1.1 主庫意外關(guān)閉問題未發(fā)生,避免方案:設(shè)置主庫的 sync_binlog 選項為 1。此選項表示 MySQL 是否控制 binlog 的刷新。當(dāng)設(shè)置為 1 時,表示每次事務(wù)提交,MySQL 都會把 binlog 刷下去,是最安全,性能損耗也最大的設(shè)置。
問題已發(fā)生,解決方案:指定備庫從下一個二進(jìn)制日志的開頭重新讀日志。但是一些日志事件將永久性丟失。可以使用 Percona Toolkit 中的 pt-table-checksum 工具來檢查主備一致性,以便于修復(fù)。
備庫意外關(guān)閉重啟時,會去讀 master.info 文件以找到上次停止復(fù)制的位置。但是在意外關(guān)閉的情況下,這個文件存儲的信息可能是錯誤的。此外,備庫也可能會嘗試重新執(zhí)行一些二進(jìn)制文件,這可能會導(dǎo)致唯一索引錯誤。我們可以通過 Percona Toolkit 中的 pt-slave-restart 工具,幫助備庫重新執(zhí)行日志文件。
如果使用的是 InnoDB 表,可以在重啟后觀察 MySQL 的錯誤日志。InnoDB 在恢復(fù)過程中會打印出恢復(fù)點(diǎn)的二進(jìn)制日志坐標(biāo),可以使用這個值來決定備庫指向主庫的偏移量。
1.3 主庫二進(jìn)制日志損壞如果主庫上的二進(jìn)制日志損壞,除了忽略損壞的位置外,別無選擇。在忽略存貨位置后,我們可以通過 FLUSH LOGS 命令在主庫開始一個新的日志文件,然后將備庫指向該文件的開始位置。
1.4 備庫中繼日志損壞如果主庫上的日志是完好的,有兩種解決方案:
1) 手工處理。找到 master binlog 日志的 pos 點(diǎn),然后重新同步。
2) 自動處理。mysql5.5 考慮到 slave 宕機(jī)中繼日志損壞這一問題,只要在 slave 的的配置文件 my.cnf 里增加一個參數(shù) relay_log_recovery=1 即可。
1.5 二進(jìn)制日志與 InnoDB 事務(wù)日志不同步由于各種各樣的原因,MySQL 的復(fù)制碰到服務(wù)器崩潰、斷電、磁盤損壞、內(nèi)存或網(wǎng)絡(luò)錯誤時,很難恢復(fù)當(dāng)時丟失的數(shù)據(jù)。幾乎都需要從某個點(diǎn)開始重啟復(fù)制。
2 未定義的服務(wù)器 ID如果沒有再 my.cnf 里定義服務(wù)器 ID,雖然可以通過 CHANGE MASTER TO 來設(shè)置備庫,但在啟動復(fù)制時會遇到:
mysql> START SLAVE; ERROR 1200 (HY000): The server us bit configured as slave; fix in config file or with CHANGE MASTER TO
這個報錯可能會讓人困惑。因為我們可能已經(jīng)通過 CHANGE MASTER TO 設(shè)置了備庫,并且通過 SHOW MASTER STATUS 也確認(rèn)了,為什么還會有這樣的報錯呢?我們通過 SELECT @@server_id 可以獲得一個值,要注意的是,這個值只是默認(rèn)值,我們必須為備庫顯式地設(shè)置服務(wù)器 ID。也就是在 my.cnf 里顯示的設(shè)置服務(wù)器 ID。
3 對未復(fù)制數(shù)據(jù)的依賴性如果在主庫上有備庫上不存在的數(shù)據(jù)庫或數(shù)據(jù)表,復(fù)制就很容易中斷,反之亦然。
對于前者,假設(shè)在主庫上有一個 single_master 表,備庫沒有。在主庫上對此表進(jìn)行操作后,備庫在嘗試回放這些操作時就會出現(xiàn)問題,導(dǎo)致復(fù)制中斷。
對于后者,假設(shè)備庫上有一個 single_slave 表,主庫沒有。在主庫上執(zhí)行創(chuàng)建 single_slave 表的語句時,備庫在回放該建表語句時就會出現(xiàn)問題。
對于此問題,我們能做的就是做好預(yù)防:
主備切換時,盡量在切換后對比數(shù)據(jù),查清楚是否有不一致的表或庫。
一定不要在備庫執(zhí)行寫操作。
4 丟失的臨時表臨時表和基于語句的復(fù)制方式不相容。如果備庫崩潰或者正常關(guān)閉,任何復(fù)制線程擁有的臨時表都會丟失。重啟備庫后,所有依賴于該臨時表的語句都會失敗。
復(fù)制時出現(xiàn)找不到臨時表的異常時,可以做:
直接跳過錯誤,或者手動地創(chuàng)建一個名字和結(jié)構(gòu)相同的表來代替消失的的臨時表。
臨時表的特性:
只對創(chuàng)建臨時表的連接可見。不會和其他擁有相同名字的臨時表的連接起沖突;
隨著連接關(guān)閉而消失,無須顯式的移除它們。
4.1 更好使用臨時表的方式保留一個專用的數(shù)據(jù)庫,在其中創(chuàng)建持久表,把它們作為偽臨時表,以模擬臨時表特性。只需要通過 CONNETCTION_ID() 的返回值,給臨時表創(chuàng)建唯一的名字。
偽臨時表的優(yōu)劣勢
優(yōu)勢:
更容易調(diào)試應(yīng)用程序??梢酝ㄟ^別的連接來查看應(yīng)用正在維護(hù)的數(shù)據(jù);
劣勢:
比臨時表多一些開銷。創(chuàng)建較慢偽臨時表會較慢,因為表的 .frm 文件需要刷新到磁盤。
5 InnoDB 加鎖讀導(dǎo)致主備數(shù)據(jù)不一致使用共享鎖,串行化更新,保證備庫復(fù)制時數(shù)據(jù)一致。
某些情況下,加鎖讀可以防止混亂。假設(shè)有兩張表:tab1 沒有數(shù)據(jù),tab2 只有一行數(shù)據(jù),值為 99。此時,有兩個事務(wù)更新數(shù)據(jù)。事務(wù) 1 將 tab2 的數(shù)據(jù)插入到 tab1,事務(wù) 2 更新 tab2。
事務(wù) 1 使用獲取 tab2 數(shù)據(jù)時,加入共享鎖,并插入 tab1;
同時,事務(wù) 2 更新 tab2 數(shù)據(jù)時,由于寫操作的排它鎖機(jī)制,無法獲取 tab2 的鎖,等待;
事務(wù) 1 插入數(shù)據(jù)后,刪除共享鎖,提交事務(wù),寫入 binlog(此時 tab1 和 tab2 的記錄值 都是 99);
事務(wù) 2 獲取到鎖,更新數(shù)據(jù),提交事務(wù),寫入 binlog(此時 tab1 的記錄值為 99,tab2 的記錄值為 100)。
上述過程中,第二步非常重要。事務(wù) 2 嘗試去更新 tab2 表,這需要在更新的行上加排他鎖(寫鎖)。排他鎖與其他鎖不相容,包括事務(wù) 1 在行記錄上加的共享鎖。因此事務(wù) 2 需要等待事務(wù) 1 完成。備庫在根據(jù) binlog 進(jìn)行復(fù)制時,會按同樣的順序先執(zhí)行事務(wù) 1,再執(zhí)行事務(wù) 2。主備數(shù)據(jù)一致。
同樣的過程,如果事務(wù) 1 在第一步時沒有加共享鎖,流程就變成:
事務(wù) 1 無鎖讀取 tab2 數(shù)據(jù),并插入 tab1(此時 tab1 和 tab2 的記錄值 都是 99);
同時,事務(wù) 2 更新 tab2 數(shù)據(jù),先與事務(wù) 1 提交事務(wù),寫入 binlog(此時 tab1 的記錄值為 99,tab2 的記錄值為 100);
事務(wù) 1 提交事務(wù),寫入 binlog(此時記錄值無變化);
mysqldump --single-transaction --all-databases --master-data=1 --host=server1 | mysql --host=server2
要注意的是,上述過程中,事務(wù) 2 先提交,先寫入 binlog。在備庫復(fù)制時,同樣先執(zhí)行事務(wù) 2,將 tab2 的記錄值更新為 100。然后執(zhí)行事務(wù) 1,讀取 tab2 數(shù)據(jù),插入 tab1,所以最終的結(jié)果是,tab1 的記錄值和 tab2 的記錄值都是 100。很明顯,數(shù)據(jù)和主庫有差異。
建議在大多數(shù)情況下將 innodb_unsafe_for_binlog 的值設(shè)置為 0。基于行的復(fù)制由于記錄了數(shù)據(jù)的變化而非語句,因此不會存在這個問題。
6 復(fù)制延遲過大產(chǎn)生延遲的兩種方式
突然產(chǎn)生延遲,然后再跟上;
穩(wěn)定的延遲增大
前者通常是由于一條執(zhí)行時間過長的 SQL 導(dǎo)致,而后者即使在沒有慢語句也會出現(xiàn)。
對于前者,我們可以通過備庫上的慢查詢?nèi)罩緛磉M(jìn)行優(yōu)化。在備庫上開啟 log_slow_slave_statement 選項,可以在慢查詢?nèi)罩局杏涗洀?fù)制線程執(zhí)行的語句。
而對于后者,沒有針對性的解決方案,只能通過各種方式提高備庫的復(fù)制效率。而當(dāng)我們想去對備庫做優(yōu)化時,會發(fā)現(xiàn),除了購買更快的磁盤和 CPU,并沒有太多的調(diào)優(yōu)空間。只能通過 MySQL 選項禁止某些額外的工作以減少備庫的復(fù)制??梢酝ㄟ^下面幾種方式:
使用 InnoDB 引擎時,設(shè)置 innodb_flush_log_at_trx_commit 值為 2,來使備庫不要頻繁的刷新磁盤,以提高事務(wù)提交效率。
禁止二進(jìn)制日志記錄。把 innodb_locks_unsafe_for_binlog 設(shè)置為 1,并把 MyISAM 的 delay_key_write 設(shè)置為 ALL。要注意的是,這些設(shè)置是以安全換取速度,在將備庫提升為主庫時,記得把這些選項設(shè)置回安全的值。
拆分效率較低的復(fù)制 SQL,分離復(fù)雜語句中的 SELECT 和 UPDATE 語句,降低復(fù)制消耗,提高效率。
總結(jié)復(fù)制問題要分清楚是 master 的問題,還是 slave 的問題。
master 問題找 binlog,slave 問題找 relaylog。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/31179.html
摘要:問題原因非正常關(guān)機(jī)導(dǎo)致沒有把數(shù)據(jù)及時的寫入硬盤。丟失的臨時表臨時表和基于語句的復(fù)制方式不相容。如果備庫崩潰或者正常關(guān)閉,任何復(fù)制線程擁有的臨時表都會丟失。臨時表的特性只對創(chuàng)建臨時表的連接可見。 主備復(fù)制過程中有很大可能會出現(xiàn)各種問題,接下來我們就討論一些比較普遍的問題,以及當(dāng)遇到這些問題時,如何解決或者預(yù)防問題發(fā)生。 1 數(shù)據(jù)損壞或丟失 問題描述:服務(wù)器崩潰、斷電、磁盤損壞、內(nèi)存或網(wǎng)絡(luò)...
摘要:也就是說線程能夠獨(dú)立于線程之前工作。復(fù)制使用了三個線程。的日志線程,將事件寫入,的線程獲取,并將其寫入,線程重放日志。 1. 復(fù)制概述 MySQL 內(nèi)置的復(fù)制功能是構(gòu)建基于 MySQL 的大規(guī)模、高性能應(yīng)用的基礎(chǔ),復(fù)制解決的基本問題是讓一臺服務(wù)器的數(shù)據(jù)與其他服務(wù)器保持同步。接下來,我們將從復(fù)制概述及原理、復(fù)制的配置、常見的問題及解決方法來學(xué)習(xí) MySQL 的復(fù)制功能。 1.1 復(fù)制解決...
摘要:也就是說線程能夠獨(dú)立于線程之前工作。復(fù)制使用了三個線程。的日志線程,將事件寫入,的線程獲取,并將其寫入,線程重放日志。 1. 復(fù)制概述 MySQL 內(nèi)置的復(fù)制功能是構(gòu)建基于 MySQL 的大規(guī)模、高性能應(yīng)用的基礎(chǔ),復(fù)制解決的基本問題是讓一臺服務(wù)器的數(shù)據(jù)與其他服務(wù)器保持同步。接下來,我們將從復(fù)制概述及原理、復(fù)制的配置、常見的問題及解決方法來學(xué)習(xí) MySQL 的復(fù)制功能。 1.1 復(fù)制解決...
閱讀 2270·2021-09-07 09:58
閱讀 3459·2019-08-30 14:07
閱讀 1341·2019-08-29 12:32
閱讀 707·2019-08-29 11:06
閱讀 3733·2019-08-26 18:18
閱讀 3784·2019-08-26 17:35
閱讀 1425·2019-08-26 11:35
閱讀 657·2019-08-26 11:35