首頁  >  文章  >  資料庫  >  MySql主從複製是什麼?如何配置實現?

MySql主從複製是什麼?如何配置實現?

青灯夜游
青灯夜游轉載
2019-02-26 10:23:592329瀏覽

這篇文章帶給大家的內容是介紹MySql主從複製是什麼?如何配置實現?有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

一、什麼是Mysql主從複製

MySQL主從複製是其最重要的功能之一。主從複製是指一台伺服器充當主資料庫伺服器,另一台或多台伺服器充當從資料庫伺服器,主伺服器中的資料自動複製到從伺服器之中。對於多層複製,資料庫伺服器即可充當主機,也可充當從機。 MySQL主從複製的基礎是主伺服器對資料庫修改記錄二進位日誌,從伺服器透過主伺服器的二進位日誌自動執行更新。

二、Mysq主從複製的類型

1、基於語句的複製:

主伺服器上面執行的語句在從伺服器上面再執行一遍,在MySQL- 3.23版本以後支援。

存在的問題:時間上可能不完全同步造成偏差,執行語句的使用者也可能是不同一個使用者。

2、基於行的複製:

將主伺服器上面改編後的內容直接複製過去,而不關心到底改變該內容是由哪一條語句引發的,在MySQL-5.0版本以後再引入。

存在的問題:例如一個薪資表中有一萬個用戶,我們把每個用戶的薪資1000,那麼基於行的複製則要複製一萬行的內容,由此造成的開銷比較大,而基於語句的複製僅僅一條語句就可以了。

3、混合類型的複製:

MySQL預設使用基於語句的複製,當基於語句的複製會引發問題的時候就會使用基於行的複製,MySQL會自動進行選擇。

在MySQL主從複製架構中,讀取操作可以在所有的伺服器上面進行,而寫入操作只能在主伺服器上面進行。主從複製架構雖然給讀操作提供了擴展,可如果寫入操作也比較多的話(多台從伺服器還要從主伺服器上面同步資料),單主模型的複製中主伺服器勢必會成為效能瓶頸。

三、Mysql主從複製的工作原理

1#、基於語句的複製:主伺服器上面執行的語句在從伺服器上面再執行一遍,在MySQL-3.23版本之後支援。

存在的問題:時間上可能不完全同步造成偏差,執行語句的使用者也可能是不同一個使用者。

2、基於行的複製:把主伺服器上面改編後的內容直接複製過去,而不關心到底改變該內容是由哪個語句引發的,在MySQL-5.0版本以後引入。

存在的問題:例如一個薪資表中有一萬個用戶,我們把每個用戶的薪資1000,那麼基於行的複製則要複製一萬行的內容,由此造成的開銷比較大,而基於語句的複製僅僅一條語句就可以了。

3、混合類型的複製:MySQL預設使用基於語句的複製,當基於語句的複製會引發問題的時候就會使用基於行的複製,MySQL會自動進行選擇。

在MySQL主從複製架構中,讀取操作可以在所有的伺服器上面進行,而寫入操作只能在主伺服器上面進行。主從複製架構雖然給讀操作提供了擴展,可如果寫入操作也比較多的話(多台從伺服器還要從主伺服器上面同步資料),單主模型的複製中主伺服器勢必會成為效能瓶頸。

三MySQL主從複製工作原理

如下圖所示:

MySql主從複製是什麼?如何配置實現?

主伺服器上面的任何修改都會保存在二進位日誌Binary log裡面,從伺服器上面啟動一個I/O thread(實際上就是一個主伺服器的客戶端進程),連接到主伺服器上面請求讀取二進位日誌,然後把讀取到的二進位日誌寫到本地的一個Realy log裡面。從伺服器上面開啟一個SQL thread定時檢查Realy log,如果發現有更改立即把更改的內容在本機上面執行一遍。

如果一主多從的話,這時主庫既要負責寫又要負責為幾個從庫提供二進位日誌。此時可以稍做調整,將二進位日誌只給某一從,這一從再開啟二進位日誌並將自己的二進位日誌再發給其它從。或者是乾脆這個從不記錄只負責將二進制日誌轉發給其它從,這樣架構起來性能可能要好得多,而且數據之間的延時應該也稍微要好一些。工作原理圖如下:

MySql主從複製是什麼?如何配置實現?

實際上在舊版的MySQL主從複製中Slave端並不是兩個行程完成的,而是由一個行程完成。但後來發現這樣做有較大的風險和效能問題,主要如下:

首先,一個進程會使複製bin-log日誌和解析日誌並在自身執行的過程成為一個串行的過程,性能受到了一定的限制,異步複製的延遲也會比較長。

另外,Slave端從Master端取得bin-log過來之後,需要接著解析日誌內容,然後在自身執行。在這個過程中,Master端可能又產生了大量變化並新增了大量的日誌。如果在這個階段Master端的儲存出現了無法修復的錯誤,那麼在這個階段所產生的所有變更都將永遠無法找回。如果在Slave端的壓力比較大的時候,這個過程的時間可能會比較長。

為了提高複製的效能並解決存在的風險,後面版本的MySQL將Slave端的複製動作交由兩個程序來完成。提出這個改進方案的人是Yahoo!的一位工程師「Jeremy Zawodny」。這樣既解決了效能問題,又縮短了非同步的延時時間,同時也減少了可能存在的資料遺失量。

當然,即使是換成了現在這樣兩個執行緒處理以後,同樣還是存在slave資料延時以及資料遺失的可能性的,畢竟這個複製是異步的。只要資料的變更不是在一個事物中,這些問題都是會存在的。如果要完全避免這些問題,就只能用MySQL的cluster來解決了。不過MySQL的cluster是記憶體資料庫的解決方案,需要將所有資料都load到記憶體中,這樣就對記憶體的需求就非常大了,對於一般的應用來說可實施性不是太大。

還有一點要提的是MySQL的複製過濾(Replication Filters),複製過濾可以讓你只複製伺服器中的一部分資料。有兩種複製過濾:在Master上過濾二進位日誌中的事件;在Slave上過濾中繼日誌中的事件。如下:

MySql主從複製是什麼?如何配置實現?

配置Master的my.cnf檔(關鍵性的設定)/etc/my.cnf

log-bin=mysql-bin

server-id   = 1

binlog-do-db=icinga

binlog-do-db=DB2     //如果备份多个数据库,重复设置这个选项即可

binlog-do-db=DB3   //需要同步的数据库,如果没有本行,即表示同步所有的数据库

binlog-ignore-db=mysql  //被忽略的数据库

配置Slave的my.cnf文件(关键性的配置)/etc/my.cnf

log-bin=mysql-bin

server-id=2

master-host=10.1.68.110

master-user=backup

master-password=1234qwer

master-port=3306

replicate-do-db=icinga

replicate-do-db=DB2

replicate-do-db=DB3   //需要同步的数据库,如果没有本行,即表示同步所有的数据库

replicate-ignore-db=mysql   //被忽略的数据库

網友說replicate-do-db的使用上可能會出些問題(http://blog.knowsky.com/19696...),自己沒有親自去測試。猜想binlog-do-db參數用於主伺服器中,透過過濾Binary Log來過濾掉設定檔中不允許複製的資料庫,也就是不寫入在Binary Log中不允許複製資料的操作日誌;而replicate-do -db用於從伺服器中,透過過濾Relay Log來過濾掉不允許複製的資料庫或表,也就是執行Relay Log中的動作時不執行那些不被允許的修改動作。這樣的話,多個從資料庫伺服器的情況:有的從伺服器既從主伺服器複製數據,又做為主伺服器向另外的從伺服器複製數據,那它的設定檔中應該可以同時存在binlog-do- db、replicate-do-db這兩個參數才對。一切都是自己的預測,關於binlog-do-db、replicate-do-db的具體使用方法還得在實際開發中一點點摸索才可以。

網路上有說,複製時忽略某些資料庫或表的操作最好不要在主伺服器上面進行,因為主伺服器忽略之後就不會再往二進位檔案中寫了,但是在從伺服器上面雖然忽略了某些資料庫但是主伺服器上面的這些操作資訊依然會被複製到從伺服器上面的relay log裡面,只是不會在從伺服器上面執行而已。我想這個意思應該是建議在從伺服器中設定replicate-do-db,而不要在主伺服器上設定binlog-do-db。

另外,不管是黑名單(binlog-ignore-db、replicate-ignore-db)或白名單(binlog-do-db、replicate-do-db)只寫一個就行了,如果同時使用那麼只有白名單生效。

四、Mysql主從複製的過程

MySQL主從複製的兩種情況:同步複製和非同步複製,在實際複製架構中大部分為非同步複製。

複製的基本程序如下:

  1. Slave上面的IO程序連接上Master,並請求從指定日誌檔案的指定位置(或從最開始的日誌)之後的日誌內容。

  2. Master接收到來自Slave的IO進程的請求後,負責複製的IO進程會根據請求資訊讀取日誌指定位置之後的日誌訊息,傳回給Slave的IO進程。傳回資訊中除了日誌所包含的資訊之外,還包括本次傳回的資訊已經到Master端的bin-log檔案的名稱以及bin-log的位置。

  3. Slave的IO程序接收到訊息後,將接收到的日誌內容依序加入Slave端的relay-log檔案的最末端,並將讀取到的Master端的bin- log的檔案名稱和位置記錄到master-info檔案中,以便在下次讀取的時候能夠清楚的告訴Master「我需要從某個bin-log的哪個位置開始往後的日誌內容,請發給我」。

  4. Slave的Sql程序偵測到relay-log中新增加了內容後,會馬上解析relay-log的內容成為在Master端真實執行時候的那些可執行的內容,並在自身執行。

五、Mysql主从复制的具体配置

复制通常用来创建主节点的副本,通过添加冗余节点来保证高可用性,当然复制也可以用于其他用途,例如在从节点上进行数据读、分析等等。在横向扩展的业务中,复制很容易实施,主要表现在在利用主节点进行写操作,多个从节点进行读操作,MySQL复制的异步性是指:事物首先在主节点上提交,然后复制给从节点并在从节点上应用,这样意味着在同一个时间点主从上的数据可能不一致。异步复制的好处在于它比同步复制要快,如果对数据的一致性要求很高,还是采用同步复制较好。

最简单的复制模式就是一主一从的复制模式了,这样一个简单的架构只需要三个步骤即可完成:

(1)建立一个主节点,开启binlog,设置服务器id;

(2)建立一个从节点,设置服务器id;

(3)将从节点连接到主节点上。

下面我们开始操作,以MySQL 5.5为例,操作系统Ubuntu12.10,Master 10.1.6.159 Slave 10.1.6.191。

apt-get install mysql-server
Master机器

Master上面开启binlog日志,并且设置一个唯一的服务器id,在局域网内这个id必须唯一。二进制的binlog日志记录master上的所有数据库改变,这个日志会被复制到从节点上,并且在从节点上回放。修改my.cnf文件,在mysqld模块下修改如下内容:

[mysqld]
server-id   = 1
log_bin     = /var/log/mysql/mysql-bin.log

log_bin设置二进制日志所产生文件的基本名称,二进制日志由一系列文件组成,log_bin的值是可选项,如果没有为log_bin设置值,则默认值是:主机名-bin。如果随便修改主机名,则binlog日志的名称也会被改变的。server-id是用来唯一标识一个服务器的,每个服务器的server-id都不一样。这样slave连接到master后,会请求master将所有的binlog传递给它,然后将这些binlog在slave上回放。为了防止权限混乱,一般都是建立一个单独用于复制的账户。

binlog是复制过程的关键,它记录了数据库的所有改变,通常即将执行完毕的语句会在binlog日志的末尾写入一条记录,binlog只记录改变数据库的语句,对于不改变数据库的语句则不进行记录。这种情况叫做基于语句的复制,前面提到过还有一种情况是基于行的复制,两种模式各有各的优缺点。

Slave机器

slave机器和master一样,需要一个唯一的server-id。

[mysqld]
server-id = 2

连接Slave到Master

在Master和Slave都配置好后,只需要把slave只想master即可

change master to master_host='10.1.6.159',master_port=3306,master_user='rep',
master_password='123456';
start slave;

接下来在master上做一些针对改变数据库的操作,来观察slave的变化情况。在修改完my.cnf配置重启数据库后,就开始记录binlog了。可以在/var/log/mysql目录下看到一个mysql-bin.000001文件,而且还有一个mysql-bin.index文件,这个mysql-bin.index文件是什么?这个文件保存了所有的binlog文件列表,但是我们在配置文件中并没有设置改值,这个可以通过log_bin_index进行设置,如果没有设置改值,则默认值和log_bin一样。在master上执行show binlog events命令,可以看到第一个binlog文件的内容。

注意:上面的sql语句是从头开始复制第一个binlog,如果想从某个位置开始复制binlog,就需要在change master to时指定要开始的binlog文件名和语句在文件中的起点位置,参数如下:master_log_file和master_log_pos。

mysql> show binlog events\G
*************************** 1. row ***************************
   Log_name: mysql-bin.000001
        Pos: 4
 Event_type: Format_desc
  Server_id: 1
End_log_pos: 107
       Info: Server ver: 5.5.28-0ubuntu0.12.10.2-log, Binlog ver: 4
*************************** 2. row ***************************
   Log_name: mysql-bin.000001
        Pos: 107
 Event_type: Query
  Server_id: 1
End_log_pos: 181
       Info: create user rep
*************************** 3. row ***************************
   Log_name: mysql-bin.000001
        Pos: 181
 Event_type: Query
  Server_id: 1
End_log_pos: 316
       Info: grant replication slave on *.* to rep identified by '123456'
3 rows in set (0.00 sec)
  • Log_name 是二进制日志文件的名称,一个事件不能横跨两个文件

  • Pos 这是该事件在文件中的开始位置

  • Event_type 事件的类型,事件类型是给slave传递信息的基本方法,每个新的binlog都已Format_desc类型开始,以Rotate类型结束

  • Server_id 创建该事件的服务器id

  • End_log_pos 该事件的结束位置,也是下一个事件的开始位置,因此事件范围为Pos~End_log_pos-1

  • Info 事件信息的可读文本,不同的事件有不同的信息

示例

在master的test库中创建一个rep表,并插入一条记录。

create table rep(name var);
insert into rep values ("guol");
flush logs;

flush logs命令强制轮转日志,生成一个新的二进制日志,可以通过show binlog events in 'xxx'来查看该二进制日志。可以通过show master status查看当前正在写入的binlog文件。这样就会在slave上执行相应的改变操作。

上面就是最简单的主从复制模式,不过有时候随着时间的推进,binlog会变得非常庞大,如果新增加一台slave,从头开始复制master的binlog文件是非常耗时的,所以我们可以从一个指定的位置开始复制binlog日志,可以通过其他方法把以前的binlog文件进行快速复制,例如copy物理文件。在change master to中有两个参数可以实现该功能,master_log_file和master_log_pos,通过这两个参数指定binlog文件及其位置。我们可以从master上复制也可以从slave上复制,假如我们是从master上复制,具体操作过程如下:

(1)为了防止在操作过程中数据更新,导致数据不一致,所以需要先刷新数据并锁定数据库:flush tables with read lock。

(2)检查当前的binlog文件及其位置:show master status。

mysql> show master status\G
*************************** 1. row ***************************
File: mysql-bin.000003
Position: 107
Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)

(3)通过mysqldump命令创建数据库的逻辑备分:mysqldump --all-databases -hlocalhost -p >back.sql。

(4)有了master的逻辑备份后,对数据库进行解锁:unlock tables。

(5)把back.sql复制到新的slave上,执行:mysql -hlocalhost -p 把master的逻辑备份插入slave的数据库中。

(6)现在可以把新的slave连接到master上了,只需要在change master to中多设置两个参数master_log_file='mysql-bin.000003'和master_log_pos='107'即可,然后启动slave:start slave,这样slave就可以接着107的位置进行复制了。

change master to master_host='10.1.6.159',master_port=3306,master_user='rep',
master_password='123456',master_log_file='mysql-bin.000003',master_log_pos='107';
start slave;

有时候master并不能让你锁住表进行复制,因为可能跑一些不间断的服务,如果这时master已经有了一个slave,我们则可以通过这个slave进行再次扩展一个新的slave。原理同在master上进行复制差不多,关键在于找到binlog的位置,你在复制的同时可能该slave也在和master进行同步,操作如下:

(1)为了防止数据变动,还是需要停止slave的同步:stop slave。

(2)然后刷新表,并用mysqldump逻辑备份数据库。

(3)使用show slave status查看slave的相关信息,记录下两个字段的值Relay_Master_Log_File和Exec_Master_Log_Pos,这个用来确定从后面哪里开始复制。

(4)对slave解锁,把备份的逻辑数据库导入新的slave的数据库中,然后设置change master to,这一步和复制master一样。

六、深入了解Mysql主从配置

1、一主多从

由一个master和一个slave组成复制系统是最简单的情况。Slave之间并不相互通信,只能与master进行通信。在实际应用场景中,MySQL复制90%以上都是一个Master复制到一个或者多个Slave的架构模式,主要用于读压力比较大的应用的数据库端廉价扩展解决方案。

MySql主從複製是什麼?如何配置實現?

在上图中,是我们开始时提到的一主多从的情况,这时主库既要负责写又要负责为几个从库提供二进制日志。这种情况将二进制日志只给某一从,这一从再开启二进制日志并将自己的二进制日志再发给其它从,或者是干脆这个从不记录只负责将二进制日志转发给其它从,这样架构起来性能可能要好得多,而且数据之间的延时应该也稍微要好一些。PS:这些前面都写过了,又复制了一遍。

2、主主复制

MySql主從複製是什麼?如何配置實現?

上图中,Master-Master复制的两台服务器,既是master,又是另一台服务器的slave。这样,任何一方所做的变更,都会通过复制应用到另外一方的数据库中。在这种复制架构中,各自上运行的不是同一db,比如左边的是db1,右边的是db2,db1的从在右边反之db2的从在左边,两者互为主从,再辅助一些监控的服务还可以实现一定程度上的高可以用。

3、主动—被动模式的Master-Master(Master-Master in Active-Passive Mode)

MySql主從複製是什麼?如何配置實現?

上图中,这是由master-master结构变化而来的,它避免了M-M的缺点,实际上,这是一种具有容错和高可用性的系统。它的不同点在于其中只有一个节点在提供读写服务,另外一个节点时刻准备着,当主节点一旦故障马上接替服务。比如通过corosync+pacemaker+drbd+MySQL就可以提供这样一组高可用服务,主备模式下再跟着slave服务器,也可以实现读写分离。

4、带从服务器的Master-Master结构(Master-Master with Slaves)

MySql主從複製是什麼?如何配置實現?

這種結構的優點就是提供了冗餘。在地理上分佈的複製結構,它不存在單一節點故障問題,而且還可以將讀取密集型的請求放到slave上。

5、MySQL-5.5支援半同步複製

早前的MySQL複製只能是基於非同步來實現,從MySQL-5.5開始,支援半自動複製。在先前的非同步(asynchronous)複製中,主庫執行完一些事務後,是不會管備庫的進度的。如果備庫處於落後,而更不幸的是主庫此時又出現Crash(例如宕機),這時備庫中的資料就是不完整的。簡而言之,在主庫發生故障的時候,我們無法使用備庫來繼續提供資料一致的服務了。 Semisynchronous Replication(半同步複製)則某程度上保證提交的事務已經傳給了至少一個備庫。 Semi synchronous中,僅保證事務的已經傳遞到備庫上,但是並不確保已經在備庫上執行完成了。

此外,還有一種情況會導致主備資料不一致。在某個session中,主庫上提交一個事務後,會等待事務傳遞給至少一個備庫,如果在這個等待過程中主庫Crash,那麼也可能備庫和主庫不一致,這是很致命的。如果主備網路故障或備庫掛了,主庫在交易提交後等待10秒(rpl_semi_sync_master_timeout的預設值)後,就會繼續。這時,主庫就會變回原來的非同步狀態。

MySQL在載入並開啟Semi-sync外掛程式後,每一個交易需等待備庫接收日誌後才會傳回給客戶端。如果做的是小事務,兩台主機的延遲又較小,則Semi-sync可以實現在效能很小損失的情況下的零資料遺失。

以上就是這篇文章的全部內容,希望能對大家的學習有所幫助。更多精彩內容大家可以追蹤php中文網相關教學欄位! ! !

以上是MySql主從複製是什麼?如何配置實現?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除