MYSQL主從複製搭建及切換操做(GTID與傳統)

以下:html

 

 

MYSQL主從複製方式有默認的複製方式異步複製,5.5版本以後半同步複製,5.6版本以後新增GTID複製,包括5.7版本的多源複製。mysql

MYSQL版本:5.7.20linux

操做系統版本:linux 6.7 64bitsql

 

一、異步複製

 

MYSQL 默認的複製方式,就是主庫寫入binlog日誌後便可成功返回客戶端,無須等待binlog日誌傳遞給從庫的過程。但這樣一旦主庫發生宕機,就有可能出現數據丟失的狀況。數據庫

 

1.1搭建異步主從

一、 server-id 不同安全

二、 開啓binlog,建議開啓log_slave_updates,讓從庫也寫binlog,方便後期擴展架構服務器

三、 binlog格式爲row。session

 

主庫操做:架構

建立主從複製帳號異步

create user 'rep'@'192.16.20.%' identified by 'mysql';

 

grant replication slave on *.* to 'rep'@'192.16.20.%';

 

 

初始化:

mysqldump -S /tmp/mysql3307.sock --single-transaction -uroot -pmysql --master-data=2 -A > salve.sql (我全庫導入的有問題,只用的test庫)

 

注意:必須加參數 –master-data=2,讓備份出來的文件中記錄備份這一刻binlog文件與position號,爲搭建主從環境作準備。查看備份文件中記錄的當前binlog文件和position號。

 

scp salve.sql 172.16.20.21:/binlogbak

 

 

mysql -S /tmp/mysql3307.sock -uroot -pmysql < slave_test.sql

 

 

在數據庫命令行執行配置主從命令。

 

change master to

    master_host='172.16.20.32',

    master_user='rep',

    master_password='mysql',

    master_port=3307,

    master_log_file='mysql-binlog.000010',

    MASTER_LOG_POS=797;

 

start slave;

stop slave;

reset slave all; 清空從庫的全部配置信息。

 

start slave;

 

當前從庫I/O和SQL thread都是呈現Yes狀態,表明從庫上面操做已經完成了。

 

 

Master_Log_File= Relay_Master_Log_File;

Read_Master_Log_Pos= Exec_Master_Log_Pos

證實目前沒有主從延遲狀態。

 

Slave_IO_Running:從庫上I/O thread 負責請求和接收主庫傳遞來的binlog信息。

Slave_SQL_Running:從庫上SQL thread負責應用relay中的binlog的信息。

 

1.2主從複製故障處理

1、主從故障之主鍵衝突,錯誤代碼爲1062

 

緣由:因爲誤操做,從從庫上執行寫操做,致使再在主庫上執行相同的操做,因爲主鍵衝突,主從複製狀態會報錯。因此生產環境建議在從庫上開啓read only,避免在從庫執行寫操做。

 

在主庫上建表t1;

如今從庫插入數據,後面再在主庫上插入相同的語句。

主庫:

 

 

從庫:

 

 

主庫執行相同語句:

 

 

從庫報錯以下:

 

 

報錯代碼:

Last_Errno: 1062

處理辦法:

 

利用percona-toolkit 工具:

mount /dev/sr0 /mnt

yum -y install perl-DBD-MySQL

./pt-slave-restart -S /tmp/mysql3307.sock -uroot -pmysql

 

 

在查看主從狀態,已經恢復正常:

 

 

2、主從故障之主庫更新數據,從庫找不到而報錯,錯誤代碼爲10032

上一個錯誤是主從都有相同的數據,咱們能夠直接經過percona-toolkit工具跳過錯誤。但若是從庫上少數據,就不能跳過錯誤了,須要找到缺乏的數據,在從庫上重新執行一遍。

故障緣由:因爲誤操做,在從庫上執行delete 刪除操做,致使主從數據不一致。這時再在主庫執行同條數據的更新操做,因爲從庫沒有該數據,SQL沒法再從庫上實現。

 

模擬故障:

先在從庫服務器的test庫下的t表中,執行delete刪除語句操做。

 

再在主庫上執行:相同數據的update更新操做。

 

 

從庫報錯以下:

 

 

報錯代碼1032。

解決辦法:

 

根據報錯信息所知道Binlog文件和position(7153)號,在主庫上,經過mysqlbinlog 命令,找到在主庫上執行的那條SQL語句致使的主從報錯。

 

/usr/local/mysql5.7/bin/mysqlbinlog --no-defaults -v -v --base64-output=decode-rows /mydata/mysql/mysql3307/logs/mysql-binlog.000010 |grep -A 10 7153

 

 

 

insert into t2 values(1,'bbb');

生產上若是丟失數以萬計條的數據,建議從新搭建主從確保數據一致性。

 

 

從庫跳過錯誤:

./pt-slave-restart -S /tmp/mysql3307.sock -uroot -pmysql

 

 

從新同步成功:

show slave status\G;

 

 

1.3主從故障之主從server-id一致

因爲粗心,安裝的時候用模板並無修改servier-id。(修改從庫server-id成不一樣的值)

 

1.4主從故障之跨庫操做,丟失數據

緣由:在主庫中設置binlog-do-db參數,使用的binlog記錄格式爲statement模式,致使在主庫上執行跨庫操做時,從庫沒有複製成功,丟失數據。

 

故障操做描述:

在主庫的參數文件中添加binlog-do-db=test,表明只複製zs這個庫,而且主庫binlog_format 設置爲statement。

 

二、半同步複製

   異步複製方式不足之處在於,當主庫把event寫入二進制日誌後,並不知道從庫是否已經接受並應用日誌了;若是主庫發生意外宕機或者是奔潰,頗有可能主庫提交的事物沒有傳到任何一臺從庫機器上。在高可用集羣架構下作主備切換,就會形成新的主庫丟失數據。

   mysql5.5版本以後引入了半同步複製功能,主從服務器必須安裝半同步複製插件,才能開啓該複製功能。該功能確保從庫接收完主庫傳遞過來的binlog內容已經寫入到本身的relay log裏面了,纔會通知主庫上面的等待線程,該操做完畢。

    若是等待超時,超過rpl_semi_sync_master_timeout 參數設置時間,則關閉半同步複製,並自動轉換爲異步複製模式,直到至少有一臺從庫通知主庫已經接收到binlog信息位置。

  半同步複製提高了主從之間數據的一致性,讓複製更加安全可靠,在mysql5.7版本中又增長了rpl_semi_sync_master_wait_point 參數,用來控制半同步模式下主庫在返回給session事物成功以前的事務提交方式。

該參數有兩個值:

 

AFTER_SYNC(缺省值):主服務器將每一個事務寫入其二進制日誌和從服務器,並將二進制日誌同步到磁盤。同步後,主設備等待從設備確認事務接收。在收到確認後,主服務器將事務提交給存儲引擎,並將結果返回給客戶端,而後客戶端能夠繼續。

AFTER_COMMIT:主服務器將每一個事務寫入其二進制日誌和從服務器,同步二進制日誌,並將事務提交給存儲引擎。主提交後等待從服務器確認事務接收。在收到確認後,主人將結果返回給客戶端,而後客戶端能夠繼續。

 

 

 

2.1半同步方式安裝

主庫上先安裝複製插件和開啓半同步複製功能:

INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

set global rpl_semi_sync_master_enabled=on;

 

 

show variables like '%rpl_semi_sync_master%';

 

 

主庫參數文件添加:

rpl_semi_sync_master_enabled=1

rpl_semi_sync_master_timeout=1000

 

show plugins;

 

 

SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS  WHERE PLUGIN_NAME LIKE '%semi%';

 

 

同理從庫也安裝插件和開啓半同步複製功能:

從庫安裝複製插件和開啓半同步複製功能:

INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

set global rpl_semi_sync_slave_enabled=on;

 

 

備庫參數文件添加:

rpl_semi_sync_slave_enabled=1

 

因爲以前是異步複製,須要重啓從庫IO線程,激活半同步複製。

 

STOP SLAVE IO_THREAD;

START SLAVE IO_THREAD;

 

此時查看主庫:

已經有一個從庫鏈接到主庫了。並且是半同步方式。

show variables like '%rpl_semi_sync_master%';

 

 

2.2半同步方式切換成異步方式

一、主庫超時超過指定參數時間

rpl_semi_sync_master_timeout 時間爲10s。生產上建議設置的儘量大。

set global rpl_semi_sync_master_timeout=xxx;

 

 

二、手動切換

主庫

set rpl_semi_sync_master_enabled=off;

從庫:

set rpl_semi_sync_slave_enabled=off

關閉從庫I/O thread

stop salve io_thread;

start salve io_thread;

 

 

三、GTID複製

GTID複製又叫全局事物ID(global transaction ID),是一個已提交事物的編號,而且是一個全局惟一的編號,MYSQL5.6版本以後在主從複製類型上新增了GTID複製。

GTID是由server_uuid和事物id組成的,即GTID=servier_uuid:transacton_id。Server_uuid是在數據庫啓動過程當中自動生成的,每臺機器的server-uuid不同。UUID存放在數據目錄的auto.cnf文件下。而trasaciton_id就是事物提交時由系統順序分配的一個不會重複的序列號。

 

3.1GTID存在的價值

一、GTID使用master_auto_position=1 代替了基於binlog和position號的主從複製搭建的方式,更便於主從複製的搭建。

二、GTID能夠知道事務在最開始是在哪一個實例上提交的。

三、GTID方便實現主從之間的failover,不再用不斷的去找position和binlog。

3.2GTID搭建模式

GTID不須要傳統的binlog和position號了,而是在從庫」change master to」時使用」master_auto_position=1」的方式搭建,這就讓操做變得更加方便和可靠了。

 

3.3配置前期準備

在安裝好主從數據庫以後:

主庫須要如下配置:

gtid_mode=on

enforce_gtid_consistency=on

log_bin=on

 

從庫須要如下配置:

 

servier-id 主從庫不能同樣。

gtid_mode=on

enforce_gtid_consistency=on

log_slave_updates=1

 

主庫操做:

建立主從複製帳號

create user 'rep'@'192.16.20.%' identified by 'mysql';

 

grant replication slave on *.* to 'rep'@'172.16.20.%';

 

show grants for 'rep'@'172.16.20.%';

 

 

若是不一樣網段建議主從各建各的。

 

初始化:

/usr/local/mysql5.7/bin/mysqldump -S /tmp/mysql3307.sock --single-transaction -uroot -pmysql --master-data=2 -A > slave.sql(我全庫導入的有問題,換成絕對路徑就行,只用的test庫)

 

注意:必須加參數 –master-data=2,讓備份出來的文件中記錄備份這一刻binlog文件與position號,爲搭建主從環境作準備。查看備份文件中記錄的當前binlog文件和position號。

 

 

scp salve.sql 172.16.20.21:/binlogbak

 

 

 

test庫操做:

mysqldump -S /tmp/mysql3307.sock --single-transaction -uroot -pmysql --master-data=2 --database test > slave_test.sql

 

注意,若是主從GTI不同,數據一致能夠:

set global gtid_purged='*******';

 

 

若是數據不同,GTID也不同,建議按照下面先reset從庫:reset master;

mysql -S /tmp/mysql3307.sock -uroot -pmysql < slave_test.sql

 

 

注意:屢次恢復會報錯,由於裏面已經有gtid的信息了。

若是你還想繼續強制恢復,能夠在從庫上 reset master ;reset後,gtid_executed,gtid_purged爲空。

show global variables like '%gtid%';

 

3.4主從配置

 

一、若是是在已經跑的服務器,你須要重啓一下mysql server。

二、啓動以前,必定要先關閉master的寫入,保證全部slave端都已經和master端數據保持同步。

三、全部slave須要加上skip_slave_start=1的配置參數,避免啓動後仍是使用老的複製協議。

 

 

在數據庫命令行執行配置主從命令。

 

change master to master_host='172.16.20.32',master_port=3307,master_user='rep',master_password='mysql',master_auto_position=1;

 

提示:master_log_file='mysql-binlog.000010',MASTER_LOG_POS=797 這兩個參數替換成了 master_auto_position=1

 

 

show slave status\G;

 

 

start slave;

 

stop slave;

reset slave all; 清空從庫的全部配置信息。

start slave;

 

 

通常複製建議半同步+GTID複製:

 

 

 

附帶主從參數:

主:

[root@mysql5 ~]# cat /etc/my3307.cnf

[client]

port = 3307

socket = /tmp/mysql5.7.sock

[mysql]

prompt="\u@db \R:\m:\s [\d]> "

no-auto-rehash

[mysqld]

user = mysql

port = 3307

basedir = /usr/local/mysql5.7

datadir = /mydata/mysql/mysql3307/data

socket = /tmp/mysql3307.sock

rpl_semi_sync_master_enabled=1

rpl_semi_sync_master_timeout=1000

lower_case_table_names=1

secure_file_priv=/tmp

character-set-server = utf8mb4

skip_name_resolve = 1

open_files_limit = 65535

back_log = 1024

max_connections = 500

max_connect_errors = 1000000

table_open_cache = 1024

table_definition_cache = 1024

table_open_cache_instances = 64

thread_stack = 512K

external-locking = FALSE

max_allowed_packet = 32M

sort_buffer_size = 4M

join_buffer_size = 4M

thread_cache_size = 768

query_cache_size = 0

query_cache_type = 0

interactive_timeout = 600

wait_timeout = 600

tmp_table_size = 32M

max_heap_table_size = 32M

slow_query_log = 1

slow_query_log_file = /mydata/mysql/mysql3307/logs/slow.log

log-error = /mydata/mysql/mysql3307/logs/error.log

long_query_time = 0.5

server-id = 3307101

log-bin = /mydata/mysql/mysql3307/logs/mysql-binlog

sync_binlog = 1

binlog_cache_size = 4M

max_binlog_cache_size = 1G

max_binlog_size = 500M

expire_logs_days = 7

master_info_repository = TABLE

relay_log_info_repository = TABLE

gtid_mode = on

enforce_gtid_consistency = 1

log_slave_updates

binlog_format = row

relay_log_recovery = 1

relay-log-purge = 1

key_buffer_size = 32M

read_buffer_size = 8M

read_rnd_buffer_size = 4M

bulk_insert_buffer_size = 64M

lock_wait_timeout = 3600

explicit_defaults_for_timestamp = 1

innodb_thread_concurrency = 0

innodb_sync_spin_loops = 100

innodb_spin_wait_delay = 30

transaction_isolation = REPEATABLE-READ

innodb_buffer_pool_size = 1024M

innodb_buffer_pool_instances = 8

innodb_buffer_pool_load_at_startup = 1

innodb_buffer_pool_dump_at_shutdown = 1

innodb_data_file_path = ibdata1:1G:autoextend

innodb_flush_log_at_trx_commit = 1

innodb_log_buffer_size = 32M

innodb_log_file_size = 2G

innodb_log_files_in_group = 2

innodb_max_undo_log_size = 4G

innodb_io_capacity = 2000

innodb_io_capacity_max = 4000

innodb_flush_neighbors = 0

innodb_write_io_threads = 8

innodb_read_io_threads = 8

innodb_purge_threads = 4

innodb_page_cleaners = 4

innodb_open_files = 65535

innodb_max_dirty_pages_pct = 50

innodb_flush_method = O_DIRECT

innodb_lru_scan_depth = 4000

innodb_checksum_algorithm = crc32

innodb_lock_wait_timeout = 10

innodb_rollback_on_timeout = 1

innodb_print_all_deadlocks = 1

innodb_file_per_table = 1

innodb_online_alter_log_max_size = 500M

internal_tmp_disk_storage_engine = InnoDB

innodb_stats_on_metadata = 0

innodb_status_file = 1

innodb_status_output = 0

innodb_status_output_locks = 0

#performance_schema

performance_schema = 1

performance_schema_instrument = '%=on'

#innodb monitor

innodb_monitor_enable="module_innodb"

innodb_monitor_enable="module_server"

innodb_monitor_enable="module_dml"

innodb_monitor_enable="module_ddl"

innodb_monitor_enable="module_trx"

innodb_monitor_enable="module_os"

innodb_monitor_enable="module_purge"

innodb_monitor_enable="module_log"

innodb_monitor_enable="module_lock"

innodb_monitor_enable="module_buffer"

innodb_monitor_enable="module_index"

innodb_monitor_enable="module_ibuf_system"

innodb_monitor_enable="module_buffer_page"

innodb_monitor_enable="module_adaptive_hash"

[mysqldump]

quick

max_allowed_packet = 32M

 

 

從:

[root@rac1 ~]# cat /etc/my3307.cnf

[client]

port = 3307

socket = /tmp/mysql5.7.sock

[mysql]

prompt="\u@db \R:\m:\s [\d]> "

no-auto-rehash

[mysqld]

user = mysql

port = 3307

basedir = /usr/local/mysql5.7

datadir = /mydata/mysql/mysql3307/data

socket = /tmp/mysql3307.sock

character-set-server = utf8mb4

lower_case_table_names=1

rpl_semi_sync_slave_enabled=1

skip_name_resolve = 1

open_files_limit = 65535

back_log = 1024

max_connections = 500

max_connect_errors = 1000000

table_open_cache = 1024

table_definition_cache = 1024

table_open_cache_instances = 64

thread_stack = 512K

external-locking = FALSE

max_allowed_packet = 32M

sort_buffer_size = 4M

join_buffer_size = 4M

thread_cache_size = 768

query_cache_size = 0

query_cache_type = 0

interactive_timeout = 600

wait_timeout = 600

tmp_table_size = 32M

max_heap_table_size = 32M

slow_query_log = 1

slow_query_log_file = /mydata/mysql/mysql3307/logs/slow.log

log-error = /mydata/mysql/mysql3307/logs/error.log

long_query_time = 0.1

server-id = 3307102

log-bin = /mydata/mysql/mysql3307/logs/mysql-binlog

sync_binlog = 1

binlog_cache_size = 4M

max_binlog_cache_size = 500m

max_binlog_size = 200m

expire_logs_days = 7

master_info_repository = TABLE

relay_log_info_repository = TABLE

gtid_mode = on

enforce_gtid_consistency = 1

log_slave_updates

binlog_format = row

relay_log_recovery = 1

relay-log-purge = 1

key_buffer_size = 32M

read_buffer_size = 8M

read_rnd_buffer_size = 4M

bulk_insert_buffer_size = 64M

lock_wait_timeout = 3600

explicit_defaults_for_timestamp = 1

innodb_thread_concurrency = 0

innodb_sync_spin_loops = 100

innodb_spin_wait_delay = 30

transaction_isolation = REPEATABLE-READ

innodb_buffer_pool_size = 1024M

innodb_buffer_pool_instances = 8

innodb_buffer_pool_load_at_startup = 1

innodb_buffer_pool_dump_at_shutdown = 1

innodb_data_file_path = ibdata1:1G:autoextend

innodb_flush_log_at_trx_commit = 1

innodb_log_buffer_size = 32M

innodb_log_file_size = 1g

innodb_log_files_in_group = 2

innodb_max_undo_log_size = 1G

innodb_io_capacity = 2000

innodb_io_capacity_max = 4000

innodb_flush_neighbors = 0

innodb_write_io_threads = 8

innodb_read_io_threads = 8

innodb_purge_threads = 4

innodb_page_cleaners = 4

innodb_open_files = 65535

innodb_max_dirty_pages_pct = 50

innodb_flush_method = O_DIRECT

innodb_lru_scan_depth = 4000

innodb_checksum_algorithm = crc32

innodb_lock_wait_timeout = 10

innodb_rollback_on_timeout = 1

innodb_print_all_deadlocks = 1

innodb_file_per_table = 1

innodb_online_alter_log_max_size = 4G

internal_tmp_disk_storage_engine = InnoDB

innodb_stats_on_metadata = 0

innodb_status_file = 1

innodb_status_output = 0

innodb_status_output_locks = 0

performance_schema = 1

performance_schema_instrument = '%=on'

#innodb monitor

innodb_monitor_enable="module_innodb"

innodb_monitor_enable="module_server"

innodb_monitor_enable="module_dml"

innodb_monitor_enable="module_ddl"

innodb_monitor_enable="module_trx"

innodb_monitor_enable="module_os"

innodb_monitor_enable="module_purge"

innodb_monitor_enable="module_log"

innodb_monitor_enable="module_lock"

innodb_monitor_enable="module_buffer"

innodb_monitor_enable="module_index"

innodb_monitor_enable="module_ibuf_system"

innodb_monitor_enable="module_buffer_page"

innodb_monitor_enable="module_adaptive_hash"

[mysqldump]

quick

max_allowed_packet = 32M

 

 

四、GTID複製與傳統複製的切換

 

主:172.16.20.32

從:172.16.10.21

 

a)    GTID切換成傳統複製

從庫信息:

show slave status\G;

 

 

主庫:

 

 

從庫切換操做:

stop slave;

 

change master to master_auto_position=0,master_host='172.16.20.32', master_port=3307,master_user='rep',master_password='mysql',Master_Log_File='mysql-binlog.000007',Master_Log_Pos=194;

 

start slave;

 

主從數據庫服務器上同時,依次執行如下操做:

set global gtid_mode='on_permissive';

 

set global gtid_mode='off_permissive';

 

主從關閉GTID功能:

set global enforce_gtid_consistency=off;

 

set global gtid_mode=off;

 

把gtid_mode=off和enforce_gtid_consistency=off寫入配置文件my3307.cnf中。重啓後能夠繼續生效,並進行測試。

 

b)    傳統複製切換成GTID過程

主從數據庫服務器同時修改如下參數:

 

set global enforce_gtid_consistency=warn; error log 不會出現警告信息,若是有,須要先修復,才能繼續後面操做。

 

set global enforce_gtid_consistency=on;

 

set global gtid_mode=off_permissive;

 

set global gtid_mode=on_permissive;

 

 

確認從庫沒等待的事務:

show global status like '%ongoing%';

 

 

0表明沒有等待的事務。

 

主從庫上同時設置gtid_mode=on;

 

set global gtid_mode=on;

 

 

show variables like '%gtid%';

 

 

把傳統複製模式改成(GTID)複製。

 

stop slave;

 

change master to master_auto_position=1;

 

 

查看並進行測試:

 

 

主:

 

 

從:

 

 

例如主庫:

 

 

從庫:

 

分類: MYSQL

相關文章
相關標籤/搜索