1. 程式人生 > 其它 >MySQL主從搭建及主從不同步問題處理

MySQL主從搭建及主從不同步問題處理

1、使用主從同步的好處:

1.通過增加從伺服器來提高資料庫的效能,在主伺服器上執行寫入和更新,在從伺服器上向外提供讀功能,可以動態地調整從伺服器的數量,從而調整整個資料庫的效能。
2.提高資料安全-因為資料已複製到從伺服器,從伺服器可以終止複製程序,所以,可以在從伺服器上備份而不破壞主伺服器相應資料
3.在主伺服器上生成實時資料,而在從伺服器上分析這些資料,從而提高主伺服器的效能

2、主從同步機制

1、slave 伺服器執行 start slave,開啟主從複製開關, slave 伺服器的 IO 執行緒請求從 master 伺服器讀取 binlog(如果該執行緒追趕上了主庫,會進入睡眠狀態)。
2、master 伺服器的更新SQL(update、insert、delete)被寫到binlog, 主庫的 binlog dump thread,把 bin log 的內容傳送到從庫。


3、從庫啟動之後,建立一個 I/O 執行緒,讀取主庫傳過來的 bin log 內容並寫到 relay log(會記錄位置資訊,以便下次繼續讀取)。
4、slave 伺服器的 SQL 執行緒會實時檢測 relay log 中新增的日誌內容,把 relay log解析成 SQL 語句,並執行。

3、MySql資料庫安裝

  先檢查系統是否裝有mysql:rpm -qa | grep mysql (無返回則沒有安裝)

  刪除可用:yum remove mysql

  下載地址:https://dev.mysql.com/downloads/mysql/

  解壓:tar -xvf /usr/local/mysql-8.0.30-linux-glibc2.12-x86_64.tar.xz -C /usr/local/

  下載mysql的repo源: wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm

  安裝mysql.rpm包 :rpm -ivh mysql-community-release-el7-5.noarch.rpm

  安裝rpm包後在 /etc/yum.repos.d 會獲取兩個yum repo源

  

  安裝mysql:yum install mysql-server

  再次檢視:rpm -qa | grep mysql

  

  如果報錯,內容含有:

Error: Package: mysql-community-libs-5.6.35-2.el7.x86_64 (mysql56-community)
           Requires: libc.so.6(GLIBC_2.17)(64bit)
Error: Package: mysql-community-server-5.6.35-2.el7.x86_64 (mysql56-community)
           Requires: libc.so.6(GLIBC_2.17)(64bit)
Error: Package: mysql-community-server-5.6.35-2.el7.x86_64 (mysql56-community)
           Requires: systemd
Error: Package: mysql-community-server-5.6.35-2.el7.x86_64 (mysql56-community)
           Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)
Error: Package: mysql-community-client-5.6.35-2.el7.x86_64 (mysql56-community)
           Requires: libc.so.6(GLIBC_2.17)(64bit)
 You could try using --skip-broken to work around the problem
 You could try running: rpm -Va --nofiles --nodigest

  解決:yum install glibc.i686 yum list libstdc++*

  登入mysql:mysql -u root

  登入報錯可能為/var/lib/mysql檔案許可權問題,解決:chown root /var/lib/mysql/

  重啟mysql:service mysqld restart

  為root新增遠端連線的能力:GRANT ALL PRIVILEGES ON . TO root@"%" IDENTIFIED BY "password";

  查詢資料庫編碼格式,確保是 UTF-8:show variables like "%char%";

  修改編碼格式為UTF-8:set names utf8;

  開放3306埠號,並重啟(centos7):

  firewall-cmd --zone=public --add-port=3306/tcp --permanent firewall-cmd --reload

4、修改主庫和從庫的配置檔案(/etc/my.cnf)

4.1更改配置檔案,首先檢查你的主伺服器上的my.cnf檔案中是否已經在[mysqld]模組下配置了log-bin和server-id

#[mysqld]標籤下追加

#表示是本機的序號為1,一般來講就是master的意思
server_id =1
#伺服器在關閉它之前在一個連線上等待行動的秒數。
wait_timeout=360000
#開啟Binlog日誌
log-bin=binlog
#開啟Binlog日誌的索引檔案
log-bin-index=binlog.index
#表示slave將複製事件寫進自己的二進位制日誌
log_slave_updates=1
#當每進行1次事務提交之後,MySQL將進行一次fsync之類的磁碟同步指令來將binlog_cache中的資料強制寫入磁碟
sync-binlog = 1
#表示自增長欄位從那個數開始,他的取值範圍是1 .. 65535
auto_increment_offset = 2
#表示自增長欄位每次遞增的量,其預設值是1,取值範圍是1 .. 65535
auto_increment_increment = 2

4.2主庫建立用AB複製所需的使用者

GRANT replication slave ON . TO 'user'@'%' identified by 'password';

flush privileges;

4.3獲取二進位制日誌的資訊並匯出資料庫,步驟:

首先登陸資料庫,然後重新整理所有的表,同時給資料庫加上一把鎖,阻止對資料庫進行任何的寫操作

flush tables with read lock;     #資料庫執行

然後執行下面的語句獲取二進位制日誌的資訊

show master status;    #資料庫執行

 File的值是當前使用的二進位制日誌的檔名,Position是該日誌裡面的位置資訊(不需要糾結這個究竟代表什麼),記住這兩個值,會在下面配置從伺服器時用到。

注意:如果之前的伺服器並沒有配置使用二進位制日誌,那麼使用上面的sql語句會顯示空,在鎖表之後,再匯出資料庫裡的資料(如果資料庫裡沒有資料,可以忽略這一步)

mysqldump -uroot -p'123456' -S /data/3306/data/mysql.sock --all-databases > /server/backup/mysql_bak.$(date +%F).sql    #伺服器執行

如果資料量很大,可以在匯出時就壓縮為原來的大概三分之一

mysqldump -uroot -p'123456' -S /data/3306/data/mysql.sock --all-databases | gzip > /server/backup/mysql_bak.$(date +%F).sql.gz  #伺服器執行

這時可以對資料庫解鎖,恢復對主資料庫的操作

unlock tables;    #資料庫執行

4.4備庫:

此時配置檔案中:relay_log、relay_log_index後面配置的資料夾可能會報錯找不到,

解決:1、配置mysql訪問此資料夾的許可權; 2、修改:relay-log=relay-log 修改:relay-log-index=relay-log.index

#[mysqld]標籤下追加
#只讀操作控制
read_only=1
#是否自動清空不再需要中繼日誌時,0不啟動
relay_log_purge=0
server_id=2
# 忽略表
replicate-wild-ignore-table=mysql.*
replicate-wild-ignore-table=sys.* #定義relay_log的位置和名稱 relay_log=/usr/local/mysql/mysql-relay-bin #定義relay_log的索引檔案位置和名稱 relay_log_index=/usr/local/mysql/mysql-relay-bin.index #伺服器在關閉它之前在一個連線上等待行動的秒數。 wait_timeout=360000

4.5重啟服務:

service mysqld restart #主備伺服器中執行

如果有多個從伺服器上,那麼每個伺服器上配置的server-id都必須不一致。從伺服器上沒必要配置log-bin,當然也可以配置log-bin選項,因為可以在從伺服器上進行資料備份和災難恢復,或者某一天讓這個從伺服器變成一個主伺服器

如果主伺服器匯出了資料,下面就匯入該檔案,如果主伺服器沒有資料,就忽略這一步

mysql -uroot -p'123456' -S /data/3306/data/mysql.sock < /server/backup/mysql_bak.2015-07-01.sql    #伺服器中執行

如果從主伺服器上拿過來的是壓縮檔案,就先解壓再匯入

配置同步引數,登陸mysql,輸入如下資訊:

change master to master_host='主庫IP', master_port=主庫埠, master_user='同步使用者', master_password='同步使用者的密碼', master_log_file='binlog.000002',master_log_pos=1797;  #備服務執行

start slave; 

 #提示報錯:Slave failed to initialize relay log info structure from the repository
 #解決
 reset slave;
 start slave;

啟動主從同步程序  

start slave;    #備服務執行

檢查狀態

show slave status \G  #備服務執行
Slave_IO_Running: Yes #I/O執行緒狀態OK 	  #負責從庫去主庫讀取二進位制日誌,並寫入到從庫的中繼日誌。
Slave_SQL_Running: Yes #SQL執行緒狀態OK	  #負責將中繼日誌轉為sql後執行。
Seconds_Behind_Master: 0             #同步效率非常好,沒有延遲

可能出現問題彙總(備)  

1、mysql主從複製異常Slave_IO_Running: NO  

*原因一*:mysql5.6以上版本使用唯一uuid表示符,資料遷移是使用的物理備份,uuid會重複,修改uuid不一致即可

vim /var/lib/mysql/auto.cnf 
[auto]
server-uuid=85dba00a-e0ef-11e9-b341-000c29812345
# 任意修改幾位,重啟mysql

*原因二* 確認server-id 是否唯一, mysql 有可能並沒有載入my.cnf 檔案中的server-id  

# 修改/etc/my.cnf
server-id=2  #主從要不一致
 
mysql>  show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 2    |
+---------------+-------+
 
mysql> set global server-id=3; # 如果與my.cnf中設定的不一樣,請修改一致
# 重啟mysql

*原因三* :這種原因有可能是主庫重啟造成的二進位制檔案位置從庫於主庫不一致。

解決: 需要手動將這些檔案二進位制日誌mysql-bin.00000x,mysql-bin.index刪除,rm -rf 掉 在重啟資料庫

*原因四* :機器之間網路不通。

*原因五* :一般是事務回滾造成的,解決辦法:

mysql> stop slave ;  
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave ;

1、mysql主從複製異常Slave_SQL_Running: NO  ;Seconds_Behind_Master: null

*原因一*1.程式可能在slave上進行了寫操作 ;2.也可能是slave機器重起後,事務回滾造成的.

解決辦法:
mysql> stop slave ;      #備
mysql> set GLOBAL SQL_SLAVE_SKIP_COUNTER=1;
mysql> start slave ;

*原因二*File和Position對應的值有所改變  

show master status;    #主
stop slave;    #備
change master to master_host='主庫IP', master_port=主庫埠, master_user='同步使用者', master_password='同步使用者的密碼', master_log_file='binlog.000002',master_log_pos=1797;  #備

5.模擬測試  

主庫 #模擬產生資料

#主庫
mysql> create database slave; #建立資料庫
mysql> use slave; #選擇資料庫
mysql> create table a(a int); #建立表
mysql> insert into a values(1); #插入資料
mysql> insert into a values(2); #插入資料

所有從庫 #檢視資料同步狀態  

mysql> show databases; #檢視當前有哪些資料庫(主庫新建的slave庫同步過來了)
mysql> use slave; #選擇資料庫
mysql> select * from a; #檢視a表資料

如果從庫的同步程序停止了,主庫的操作還會往從庫中同步嗎?會丟資料嗎?

所有從庫 #模擬服務出現問題

service mysql stop #停止mysql服務,模擬從庫出現問題 

主庫 #從庫出現問題,此期間主庫正常操作 

use slave; #選擇資料庫
insert into a values(3); #插入資料
insert into a values(4); #插入資料

所有從庫 #問題解決,檢視有沒有丟資料  

service mysql start #啟動Mysql服務
mysql >use slave; #選擇資料庫
mysql >select * from a; #資料自動同步過來了,主庫的資料沒有丟失

6.結語  

看到這裡的同學,你一定會對 MySQL 複製技術有一個清晰的瞭解,認識到複製是資料同步的基礎,而二進位制日誌就是複製的基石。

轉載請備註原文連結!!!