複製的原理其實很簡單,僅分爲如下三步:mysql
日誌文件中記錄的究竟是什麼呢?mysql支持了兩種日誌格式,這兩種日誌格式也體現了各自的複製方式sql
基於語句的複製至關於邏輯複製,即二進制日誌記錄了操做的語句,經過這些語句在從庫進行重放來實現複製。數據庫
這種方式簡單,二進制日誌佔用空間少,使得帶寬小傳輸效率較高。可是基於語句的更新依賴於其餘因素,好比插入數據時利用時間戳函數調用當前時間做爲時間值也會出現問題,由於因爲主從之間的延遲致使時間值不一致。存儲過程和觸發器也可能出現問題。緩存
因此在開發當中咱們應該將邏輯儘可能放在代碼層,而不該放到mysql中,不易擴展。安全
基於行的複製至關於物理複製,即二進制日誌記錄了實際更新數據的每一行。這樣致使行復制的壓力比較大,由於日誌佔用空間較大,傳輸佔用帶寬也較高。可是比基於語句複製更加精確,能夠屏蔽一些因爲主庫從庫之間的差別致使的不一致。如剛纔提到的時間戳函數。網絡
例如一條更新用戶總積分的語句,須要統計用戶的全部積分再寫入用戶表。若是是基於語句複製的話,從庫須要再一次統計用戶的積分,而基於行復制就直接更新記錄,無需再統計用戶積分。多線程
由於兩種方式各有優缺點,因此mysql在這兩種複製模式進行動態的切換。默認是語句。架構
# 若是在雙主複製結構中沒有設置ID的話就會致使循環同步問題 server_id=1 # 即日誌中記錄的是語句仍是行更新或者是混合 binlog_format=mixed # 在進行n次事務提交之後,Mysql將執行一次fsync的磁盤同步指令。將緩衝區數據刷新到磁盤。 # 爲0的話由Mysql本身控制頻率。 sync_binlog=n # 爲0的話,log buffer將每秒一次地寫入log file中而且刷新到磁盤。 # mysqld進程崩潰會丟失一秒內的全部事務。 # 爲1的話,每次事務log buffer會寫入log file並刷新到磁盤。(較爲安全) # 在崩潰的時候,僅會丟失一個事務。 # 爲2的話,每次事務log buffer會寫入log file,但一秒一次刷新到磁盤 innodb_flush_logs_at_trx_commit=0 # 阻止從庫崩潰後自動啓動複製,給一些時間來修復可能的問題, # 崩潰後再自動複製可能會致使更多的問題。而且自己就是不一致的 skip_slave_start=1 # 是否將從庫同步的事件也記錄到從庫自身的bin-log中 # 容許備庫將重放的事件也記錄到自身的二進制日誌中去,能夠將備庫當作另一臺主庫的從庫 log_slave_update # 日誌過時刪除時間,延遲嚴重的話會致使日誌文件佔用磁盤 expire_logs_days=7
innodb_flush_logs_at_trx_commit的三個參數很容易弄混。如下是詳細的解析:併發
mysql先將日誌寫到log buffer緩衝區當中,再將log buffer緩衝區的數據寫到log file日誌文件中,此時寫入的是內存中的log file,最終仍需操做系統將內存中的數據刷寫到磁盤上。 參數0:mysql每秒都會將log buffer的數據寫入到log file中而且刷新到磁盤。意味着mysql崩潰的時候將會丟失一秒內的全部事務。 參數1:每次事務提交都會將log buffer寫入到log file並刷新到磁盤。意味着在mysql崩潰的時候,僅會丟失一個事務。 參數2:每次事務提交都會將log buffer寫入到log file但不一樣時寫入到磁盤,由mysql自行控制每秒將log file刷寫到磁盤上,當mysql崩潰的時候操做系統沒崩潰的時候,log_file中僅會丟失一個事務,操做系統仍會將log file刷寫到磁盤,而若是操做系統也崩潰或斷電的話,則會丟失一秒內的事務。
推薦使用:負載均衡
innodb_flush_logs_at_trx_commit=2 sync_binlog=500
性能會較快
innodb_flush_logs_at_trx_commit=1 sync_binlog=1
較爲安全
當主庫的TPS併發較高時,因爲主庫上面是多線程寫入的,而從庫的SQL線程是單線程的,致使從庫SQL可能會跟不上主庫的處理速度(生產者比消費者快,致使商品堆積)。
從庫配置
sync_binlog=0 innodb_flush_log_at_trx_commit=2 logs-slave-updates=0 增大 innodb_buffer_pool_size
讓更多操做在Mysql內存中完成,減小磁盤操做。或者升級Mysql5.7版本使用並行複製。
筆者我的心得,若有錯誤懇請網友評論指正。
來源:juejin.cn/post/6844903968259178504