主從同步
主機環境
mysql的安裝可以參考:https://www.cnblogs.com/brianzhu/p/8575243.html
Centos7版本
master:192.168.192.128
slave: 192.168.192.129
注意下面幾點:
1)要保證同步服務期間之間的網絡聯通。即能相互ping通,能使用對方授權信息連接到對方數據庫(防火牆開放3306端口)。
2)關閉selinux。
3)同步前,雙方數據庫中需要同步的數據要保持一致。這樣,同步環境實現后,再次更新的數據就會如期同步了.
實現過程
為了測試效果,先在master機器上創建數據庫並插入一些數據 創建數據庫 mysql> create database brian character set utf8 collate utf8_general_ci; Query OK, 1 row affected (0.00 sec) 切到新創建的數據中創建表結構 mysql> use brian; Database changed mysql> create table if not exists haha (id int(10) primary key auto_increment,name varchar(50) not null); Query OK, 0 rows affected (0.01 sec) 連續插入兩條數據 mysql> insert into brian.haha values(1,"zhujingzhi"),(2,"xiaozhi"); Query OK, 2 rows affected (0.03 sec) Records: 2 Duplicates: 0 Warnings: 0 查看表中的數據 mysql> select * from brian.haha; +----+------------+ | id | name | +----+------------+ | 1 | zhujingzhi | | 2 | xiaozhi | +----+------------+ 2 rows in set (0.00 sec) ------------------------------------------------------------------------------------------------------ 溫馨提示: 修改庫或表的字符集 mysql> alter database brian default character set utf8; # 修改brian庫的字符集 mysql> alter table brian.haha default character set utf8; # 修改brian.haha表的字符集 添加主鍵 mysql> Alter table brian.haha add primary key(id); # brian.haha表的id添加主鍵 mysql> Alter table brian.haha change id id int(10) not null auto_increment; # 自增長屬性 刪除主鍵時要先刪除自增長,再刪除主鍵 mysql> Alter table brian.haha change id id int(10); # 刪除自增長 mysql> Alter table brian.haha drop primary key; # 刪除主建 ------------------------------------------------------------------------------------------------------ 下面是master數據庫上的操作: 1)設置master數據庫的my.cnf文件(在[mysqld]配置區域添加下面內容) [root@master1 ~]# vim /etc/my.cnf ......... server-id=1 #數據庫唯一ID,主從的標識號絕對不能重復。 log-bin=mysql-bin #開啟bin-log,並指定文件目錄和文件名前綴 binlog-do-db=brian #需要同步的數據庫。如果是多個同步庫,就以此格式另寫幾行即可。如果不指明對某個具體庫同步,就去掉此行,表示同步所有庫(除了ignore忽略的庫)。 binlog-ignore-db=mysql #不同步mysql系統數據庫。如果是多個不同步庫,就以此格式另寫幾行;也可以在一行,中間逗號隔開。 sync_binlog = 1 #確保binlog日志寫入后與硬盤同步 binlog_checksum = crc32 #跳過現有的采用checksum的事件,mysql5.6.5以后的版本中binlog_checksum=crc32,而低版本都是binlog_checksum=none binlog_format = mixed #bin-log日志文件格式,設置為MIXED可以防止主鍵重復。 validate_password_policy=0 #指定密碼策略 validate_password = off #禁用密碼策略 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 溫馨提示:在主服務器上最重要的二進制日志設置是sync_binlog,這使得mysql在每次提交事務的時候把二進制日志的內容同步到磁盤上,即使服務器崩潰也會把事件寫入日志中。 sync_binlog這個參數是對於MySQL系統來說是至關重要的,他不僅影響到Binlog對MySQL所帶來的性能損耗,而且還影響到MySQL中數據的完整性。對於"sync_binlog"參數的各種設置的說明如下: sync_binlog=0,當事務提交之后,MySQL不做fsync之類的磁盤同步指令刷新binlog_cache中的信息到磁盤,而讓Filesystem自行決定什么時候來做同步,或者cache滿了之后才同步到磁盤。 sync_binlog=n,當每進行n次事務提交之后,MySQL將進行一次fsync之類的磁盤同步指令來將binlog_cache中的數據強制寫入磁盤。 在MySQL中系統默認的設置是sync_binlog=0,也就是不做任何強制性的磁盤刷新指令,這時候的性能是最好的,但是風險也是最大的。因為一旦系統Crash,在binlog_cache中的所有binlog信息都會被丟失。 而當設置為“1”的時候,是最安全但是性能損耗最大的設置。因為當設置為1的時候,即使系統Crash,也最多丟失binlog_cache中未完成的一個事務,對實際數據沒有任何實質性影響。 從以往經驗和相關測試來看,對於高並發事務的系統來說,“sync_binlog”設置為0和設置為1的系統寫入性能差距可能高達5倍甚至更多。 ---------------------------------------------------------------------------------------------------------------------------------------------------------------- 2)導出master數據庫多余slave數據庫中的數據,然后導入到slave數據庫中。保證雙方在同步環境實現前的數據一致。 導出數據庫之前先鎖定數據庫 mysql> flush tables with read lock; # 數據庫只讀鎖定命令,防止導出數據庫的時候有數據寫入。unlock tables命令解除鎖定 Query OK, 0 rows affected (0.00 sec) 導出master數據庫中多余的brian庫(master數據庫的root用戶登陸密碼:12345) [root@master1 ~]# mysqldump -uroot brian -p12345 > /opt/brian.sql mysqldump: [Warning] Using a password on the command line interface can be insecure. 上面給出了一個警告,意思是在命令行使用密碼是不安全的(引起的原因是我們在-p后面直接寫上了密碼) 溫馨提示:在生產環境中當然是不建議直接在命令行寫密碼的 將導出的sql文件上傳到slave機器上 [root@master1 ~]# scp /opt/brian.sql root@192.168.192.129:/opt/ [root@master1 ~]# rsync -e "ssh -p22" -avpgolr /opt/brian.sql 192.168.192.129:/opt/ # rsync的方式需要服務器上安裝rsync包(yum -y install rsync) 3)設置數據同步用戶並賦予權限 mysql> grant replication slave,replication client,select on *.* to slave@'192.168.192.%' identified by 'Slave@123'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec) -------------------------------------------------------------------------------- 溫馨提示: 權限查看方式 mysql> show grants; mysql> show grants for slave@'192.168.192.%'; -------------------------------------------------------------------------------- 4)查看主服務器master狀態(注意File與Position項,從服務器需要這兩項參數) mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000001 | 630 | brian | mysql | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) 下面是slave數據庫上的操作: 1)設置slave數據庫的my.cnf配置文件 [root@node1 ~]# vim /etc/my.cnf ........ server-id=2 #數據庫唯一ID,主從的標識號絕對不能重復 log-bin=mysql-bin #啟動MySQ二進制日志系統 replicate-do-db=brian #需要同步的數據庫名。如果不指明同步哪些庫,就去掉這行,表示所有庫的同步(除了ignore忽略的庫)。 replicate-ignore-db=mysql #不同步mysql系統數據庫 slave-skip-errors = all #跳過所有的錯誤錯誤,繼續執行復制操作 validate_password_policy=0 #指定密碼策略 validate_password = off #禁用密碼策略 ----------------------------------------------------------------------------------------------- 溫馨提示: 當只針對某些庫的某張表進行同步時,如下,只同步brian庫的haha表和zjz庫的heihei表: replicate-do-db = brian replicate-wild-do-table = brian.haha //當只同步幾個或少數表時,可以這樣設置。注意這要跟上面的庫指定配合使用; replicate-do-db = zjz replicate-wild-do-table = brian.heihei //如果同步的庫的表比較多時,就不能這樣一一指定了,就把這個選項配置去掉,直接根據指定的庫進行同步。 ----------------------------------------------------------------------------------------------- 2)在slave數據庫中導入從master傳過來的數據 先創建一個brian空庫,否則下面導入數據時會報錯說此庫不存在 mysql> create database brian character set utf8 collate utf8_general_ci; Query OK, 1 row affected (0.00 sec) 切到新創建的數據中 mysql> use brian; Database changed 導入sql文件(下面會出現很多OK的輸出) mysql> source /opt/brian.sql; Query OK, 0 rows affected (0.00 sec) Query OK, 0 rows affected (0.00 sec) ........... 3)配置主從同步指令 設置之前先把從庫停掉 mysql> stop slave; Query OK, 0 rows affected, 1 warning (0.00 sec) 配置主從 mysql> change master to master_host='192.168.192.128',master_port=3306,master_user='slave',master_password='Slave@123',master_log_file='mysql-bin.000001',master_log_pos=630; Query OK, 0 rows affected, 2 warnings (0.01 sec) 啟動主從 mysql> start slave; Query OK, 0 rows affected (0.00 sec) 查看同步狀態(Slave_IO_Running和Slave_SQL_Running為YES表示主從配置成功) mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.192.128 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000001 Read_Master_Log_Pos: 630 Relay_Log_File: node1-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000001 Slave_IO_Running: Yes Slave_SQL_Running: Yes Replicate_Do_DB: brian Replicate_Ignore_DB: mysql 查看slave數據庫中的數據情況 mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | brian | | mysql | | performance_schema | | sys | +--------------------+ 5 rows in set (0.00 sec) mysql> select * from brian.haha; +----+------------+ | id | name | +----+------------+ | 1 | zhujingzhi | | 2 | xiaozhi | +----+------------+ 2 rows in set (0.00 sec) 下面測試下Mysql主從同步的效果 現在主數據庫上寫入新數據 mysql> insert into brian.haha values(200,"zjz"); ERROR 1223 (HY000): Can't execute the query because you have a conflicting read lock 上面錯誤的原因是因為剛剛在導出的時候加鎖了還未解鎖 解鎖 mysql> unlock tables; Query OK, 0 rows affected (0.00 sec) 插入數據 mysql> insert into brian.haha values(200,"zjz"); Query OK, 1 row affected (0.00 sec) 然后在slave數據庫上查看,發現master上新寫入的數據已經同步過來了 mysql> select * from brian.haha; +-----+------------+ | id | name | +-----+------------+ | 1 | zhujingzhi | | 2 | xiaozhi | | 200 | zjz | +-----+------------+ 3 rows in set (0.00 sec)
至此,主從同步環境已經實現!
溫馨提示:如果是新部署的環境,什么數據都沒有的情況下,也不需要執行導入導出,直接配置主從就行,沒有要指定的同步那個庫,也可以在my.cnf中修改
主主同步
主機環境
mysql的安裝可以參考:https://www.cnblogs.com/brianzhu/p/8575243.html
Centos7版本
master:192.168.192.128
slave: 192.168.192.129
注意下面幾點:
1)要保證同步服務期間之間的網絡聯通。即能相互ping通,能使用對方授權信息連接到對方數據庫(防火牆開放3306端口)。
2)關閉selinux。
3)同步前,雙方數據庫中需要同步的數據要保持一致。這樣,同步環境實現后,再次更新的數據就會如期同步了.
主主復制的缺點和解決方法
根據上面的主從環境部署,master和slave已經實現同步,即在master上寫入新數據,自動同步到slave。而從庫只能讀不能寫,一旦從庫有寫入數據,就會造成主從數據不一致!
下面就說下Mysql主主復制環境,在slave上更新數據時,master也能自動同步過來。
---------------------------------------------------------------------------
溫馨提示:
在做主主同步前,提醒下需要特別注意的一個問題:
主主復制和主從復制有一些區別,因為多主中都可以對服務器有寫權限,所以設計到自增長重復問題,例如:
出現的問題(多主自增長ID重復)
1)首先在A和B兩個庫上創建test表結構;
2)停掉A,在B上對數據表test(存在自增長屬性的ID字段)執行插入操作,返回插入ID為1;
3)然后停掉B,在A上對數據表test(存在自增長屬性的ID字段)執行插入操作,返回的插入ID也是1;
4)然后 同時啟動A,B,就會出現主鍵ID重復
解決方法:
只要保證兩台服務器上的數據庫里插入的自增長數據不同就可以了
如:A插入奇數ID,B插入偶數ID,當然如果服務器多的話,還可以自定義算法,只要不同就可以了
在下面例子中,在兩台主主服務器上加入參數,以實現奇偶插入!
記住:在做主主同步時需要設置自增長的兩個相關配置,如下:
auto_increment_offset 表示自增長字段從那個數開始,取值范圍是1 .. 65535。這個就是序號。如果有n台mysql機器,則從第一台開始分為設1,2...n
auto_increment_increment 表示自增長字段每次遞增的量,其默認值是1,取值范圍是1 .. 65535。如果有n台mysql機器,這個值就設置為n
在主主同步配置時,需要將兩台服務器的:
auto_increment_increment 增長量都配置為2
auto_increment_offset 分別配置為1和2。這是序號,第一台從1開始,第二台就是2,以此類推.....
這樣才可以避免兩台服務器同時做更新時自增長字段的值之間發生沖突。(針對的是有自增長屬性的字段)
---------------------------------------------------------------------------
實現過程
1)在master上的my.cnf配置 [root@master1 ~]# vim /etc/my.cnf ......... server-id=1 #數據庫唯一ID,主從的標識號絕對不能重復。 log-bin=mysql-bin #開啟bin-log,並指定文件目錄和文件名前綴 binlog-ignore-db=mysql #不同步mysql系統數據庫。如果是多個不同步庫,就以此格式另寫幾行;也可以在一行,中間逗號隔開。 sync_binlog = 1 #確保binlog日志寫入后與硬盤同步 binlog_checksum = crc32 #跳過現有的采用checksum的事件,mysql5.6.5以后的版本中binlog_checksum=crc32,而低版本都是binlog_checksum=none binlog_format = mixed #bin-log日志文件格式,設置為MIXED可以防止主鍵重復。 auto-increment-increment = 2 #自增長字段每次遞增2 auto-increment-offset = 1 #自增長字段從1開始 slave-skip-errors = all #跳過所有的錯誤錯誤,繼續執行復制操作 validate_password_policy=0 #指定密碼策略 validate_password = off #禁用密碼策略 重啟MySQL [root@master1 ~]# systemctl restart mysqld 數據同步授權(iptables防火牆開啟3306端口,要確保對方機器能使用下面權限連接到本機mysql) mysql> grant replication slave,replication client,select on *.* to slave@'192.168.192.%' identified by 'Slave@123'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec) 最好將庫鎖住,僅僅允許讀,以保證數據一致性;待主主同步環境部署后再解鎖;鎖住后,就不能往表里寫數據,但是重啟mysql服務后就會自動解鎖! 注意該參數設置后,如果自己同步對方數據,同步前一定要記得先解鎖! mysql> flush tables with read lock; Query OK, 0 rows affected (0.00 sec) 查看服務器master狀態(注意File與Position項,從服務器需要這兩項參數) mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 154 | | mysql | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) 2)在slave上的my.cnf配置 [root@node1 ~]# vim /etc/my.cnf ......... server-id=2 #數據庫唯一ID,主從的標識號絕對不能重復。 log-bin=mysql-bin #開啟bin-log,並指定文件目錄和文件名前綴 binlog-ignore-db=mysql #不同步mysql系統數據庫。如果是多個不同步庫,就以此格式另寫幾行;也可以在一行,中間逗號隔開。 sync_binlog = 1 #確保binlog日志寫入后與硬盤同步 binlog_checksum = crc32 #跳過現有的采用checksum的事件,mysql5.6.5以后的版本中binlog_checksum=crc32,而低版本都是binlog_checksum=none binlog_format = mixed #bin-log日志文件格式,設置為MIXED可以防止主鍵重復。 auto-increment-increment = 2 #自增長字段每次遞增2 auto-increment-offset = 2 #自增長字段從1開始 slave-skip-errors = all #跳過所有的錯誤錯誤,繼續執行復制操作 validate_password_policy=0 #指定密碼策略 validate_password = off #禁用密碼策略 重啟MySQL [root@node1 ~]# systemctl restart mysqld 數據同步授權(iptables防火牆開啟3306端口,要確保對方機器能使用下面權限連接到本機mysql) 同理,slave也要授權給master機器遠程同步數據的權限 mysql> grant replication slave,replication client,select on *.* to slave@'192.168.192.%' identified by 'Slave@123'; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> flush privileges; Query OK, 0 rows affected (0.01 sec) 最好將庫鎖住,僅僅允許讀,以保證數據一致性;待主主同步環境部署后再解鎖;鎖住后,就不能往表里寫數據,但是重啟mysql服務后就會自動解鎖! 注意該參數設置后,如果自己同步對方數據,同步前一定要記得先解鎖! mysql> flush tables with read lock; Query OK, 0 rows affected (0.00 sec) 查看服務器slave狀態(注意File與Position項,從服務器需要這兩項參數) mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000002 | 640 | | mysql | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec) 3)執行主張同步操作 先在slave數據庫上做同步master的設置。(確保slave上要同步的數據,提前在master上存在。最好雙方數據保持一致) mysql> unlock tables; Query OK, 0 rows affected (0.00 sec) mysql> stop slave; Query OK, 0 rows affected (0.00 sec) mysql> change master to master_host='192.168.192.128',master_user='slave',master_password='Slave@123',master_log_file='master-bin.000003',master_log_pos=154; Query OK, 0 rows affected, 2 warnings (0.00 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.192.128 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 154 Relay_Log_File: node1-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes 這樣就實現了slave->master的同步環境 再在master數據庫上做同步slave的設置。(確保slave上要同步的數據,提前在master上存在。最好雙方數據保持一致) mysql> unlock tables; Query OK, 0 rows affected (0.00 sec) mysql> stop slave; Query OK, 0 rows affected, 1 warning (0.00 sec) mysql> change master to master_host='192.168.192.129',master_user='slave',master_password='Slave@123',master_log_file='mysql-bin.000002',master_log_pos=640; Query OK, 0 rows affected, 2 warnings (0.01 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> show slave status\G; *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 192.168.192.129 Master_User: slave Master_Port: 3306 Connect_Retry: 60 Master_Log_File: mysql-bin.000002 Read_Master_Log_Pos: 640 Relay_Log_File: master1-relay-bin.000002 Relay_Log_Pos: 320 Relay_Master_Log_File: mysql-bin.000002 Slave_IO_Running: Yes Slave_SQL_Running: Yes 這樣就實現了master->slave的同步環境。至此,主主雙向同步環境已經實現! 4)最后測試下Mysql主主同步的效果 在master上寫入新數據 mysql> select * from brian.haha; +-----+------------+ | id | name | +-----+------------+ | 1 | zhujingzhi | | 2 | xiaozhi | | 200 | zhujingzhi | +-----+------------+ 3 rows in set (0.01 sec) mysql> insert into brian.haha values(211,"xiaotiantian"); Query OK, 1 row affected (0.01 sec) 在slave數據庫中查看,發現master新寫入的數據已經同步過來了 mysql> select * from brian.haha; +-----+--------------+ | id | name | +-----+--------------+ | 1 | zhujingzhi | | 2 | xiaozhi | | 200 | zhujingzhi | | 211 | xiaotiantian | +-----+--------------+ 4 rows in set (0.00 sec) 在slave上刪除數據 mysql> delete from brian.haha where id=200; Query OK, 1 row affected (0.00 sec) 在master數據庫中查看 mysql> select * from brian.haha; +-----+--------------+ | id | name | +-----+--------------+ | 1 | zhujingzhi | | 2 | xiaozhi | | 211 | xiaotiantian | +-----+--------------+ 3 rows in set (0.00 sec)
至此,主主同步環境已經實現!