為什麼要做主從複制?
1、在業務複雜的系統中,有這麼一個情景,有一句sql語句需要鎖表,導緻暫時不能使用讀的服務,那麼就很影響運作中的業務,使用主從複制,讓主庫負責寫,從庫負責讀,這樣,即使主庫出現了鎖表的情景,通過讀從庫也可以保證業務的正常運作。
2、做資料的熱備
3、架構的擴充。業務量越來越大,I/O通路頻率過高,單機無法滿足,此時做多庫的存儲,降低磁盤I/O通路的頻率,提高單個機器的I/O性能。
mysql主從複制的原理是什麼?
binlog: binary log,主庫中儲存更新事件日志的二進制檔案。
主從複制的基礎是主庫記錄資料庫的所有變更記錄到binlog。binlog是資料庫中儲存配置中過期時間内所有修改資料庫結構或内容的一個檔案。如果過期時間是10d的話,那麼就是最近10d的資料庫修改記錄。
mysql主從複制是一個異步的複制過程,主庫發送更新事件到從庫,從庫讀取更新記錄,并執行更新記錄,使得從庫的内容與主庫保持一緻。
在主庫裡,隻要有更新事件出現,就會被依次地寫入到binlog裡面,是之後從庫連接配接到主庫時,從主庫拉取過來進行複制操作的資料源。
binlog輸出線程。每當有從庫連接配接到主庫的時候,主庫都會建立一個線程然後發送binlog内容到從庫。
對于每一個即将發送給從庫的sql事件,binlog輸出線程會将其鎖住。一旦該事件被線程讀取完之後,該鎖會被釋放,即使在該事件完全發送到從庫的時候,該鎖也會被釋放。
在從庫裡,當複制開始的時候,從庫就會建立兩個線程進行處理:
從庫I/O線程。當START SLAVE語句在從庫開始執行之後,從庫建立一個I/O線程,該線程連接配接到主庫并請求主庫發送binlog裡面的更新記錄到從庫上。
從庫I/O線程讀取主庫的binlog輸出線程發送的更新并拷貝這些更新到本地檔案,其中包括relay log檔案。
從庫的SQL線程。從庫建立一個SQL線程,這個線程讀取從庫I/O線程寫到relay log的更新事件并執行。
可以知道,對于每一個主從複制的連接配接,都有三個線程。擁有多個從庫的主庫為每一個連接配接到主庫的從庫建立一個binlog輸出線程,每一個從庫都有它自己的I/O線程和SQL線程。
從庫通過建立兩個獨立的線程,使得在進行複制時,從庫的讀和寫進行了分離。是以,即使負責執行的線程運作較慢,負責讀取更新語句的線程并不會是以變得緩慢。比如說,如果從庫有一段時間沒運作了,當它在此啟動的時候,盡管它的SQL線程執行比較慢,它的I/O線程可以快速地從主庫裡讀取所有的binlog内容。這樣一來,即使從庫在SQL線程執行完所有讀取到的語句前停止運作了,I/O線程也至少完全讀取了所有的内容,并将其安全地備份在從庫本地的relay log,随時準備在從庫下一次啟動的時候執行語句。
整個主從複制的流程可以通過以下步驟了解:
- 步驟一:主庫db的更新事件(update、insert、delete)被寫到binlog
- 步驟二:從庫發起連接配接,連接配接到主庫
- 步驟三:此時主庫建立一個binlog dump thread,把binlog的内容發送到從庫
- 步驟四:從庫啟動之後,建立一個I/O線程,讀取主庫傳過來的binlog内容并寫入到relay log
- 步驟五:還會建立一個SQL線程,從relay log裡面讀取内容,從
位置開始執行讀取到的更新事件,将更新内容寫入到slave的db
Exec_Master_Log_Pos
主從複制配置
步驟如下:
主伺服器:從伺服器ip位址分别為
192.168.145.222、192.168.145.226
1、修改主伺服器master:
vi /etc/my.cnf
[mysqld]
log-bin=mysql-bin #[必須]啟用二進制日志
server-id=222 #[必須]伺服器唯一ID,預設是1,一般取IP最後一段
2、修改從伺服器slave:
vi /etc/my.cnf
[mysqld]
log-bin=mysql-bin #[不是必須]啟用二進制日志
server-id=226 #[必須]伺服器唯一ID,預設是1,一般取IP最後一段
3、重新開機兩台伺服器的mysql
systemctl restart mariadb
4、在主伺服器上建立帳戶并授權slave:
mysql
mysql>GRANT REPLICATION SLAVE ON *.* to 'mysync'@'%' identified by 'q123456'; //一般不用root帳号,“%”表示所有用戶端都可能連,隻要帳号,密碼正确,此處可用具體用戶端IP代替,如192.168.145.226,加強安全。
5、登入主伺服器的mysql,查詢master的狀态
mysql>show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000004 | 308 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
注:執行完此步驟後不要再操作主伺服器MYSQL,防止主伺服器狀态值變化
6、配置從伺服器Slave:
注意mysql-bin.000004和308是第五步中的File和Position
mysql>change master to master_host='192.168.145.222',master_user='mysync',master_password='q123456',master_log_file='mysql-bin.000004',master_log_pos=308; //注意mysql-bin.000004和308是第五步中的File和
Position Mysql>start slave; //啟動從伺服器複制功能
7、檢查從伺服器複制功能狀态:
mysql> show slave status\G
************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.2.222 //主伺服器位址
Master_User: mysync //授權帳戶名,盡量避免使用root
Master_Port: 3306 //資料庫端口,部分版本沒有此行
Connect_Retry: 60
Master_Log_File: mysql-bin.000004
Read_Master_Log_Pos: 600 //#同步讀取二進制日志的位置,大于等于Exec_Master_Log_Pos
Relay_Log_File: ddte-relay-bin.000003
Relay_Log_Pos: 251
Relay_Master_Log_File: mysql-bin.000004
Slave_IO_Running: Yes //此狀态必須YES
Slave_SQL_Running: Yes //此狀态必須YES
......
注:Slave_IO及Slave_SQL程序必須正常運作,即YES狀态,否則都是錯誤的狀态(如:其中一個NO均屬錯誤)。
以上操作過程,主從伺服器配置完成。
9、主從伺服器測試:
主伺服器Mysql,建立資料庫,并在這個庫中建表插入一條資料:
mysql> create database hi_db;
Query OK, 1 row affected (0.00 sec)
mysql> use hi_db;
Database changed
mysql> create table hi_tb(id int(3),name char(10));
Query OK, 0 rows affected (0.00 sec)
mysql> insert into hi_tb values(001,'bobu');
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hi_db |
| mysql |
| test |
+--------------------+
4 rows in set (0.00 sec)
從伺服器Mysql查詢:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| hi_db | //I'M here,大家看到了吧
| mysql |
| test |
+--------------------+
4 rows in set (0.00 sec)
mysql> use hi_db
Database changed
mysql> select * from hi_tb; //檢視主伺服器上新增的具體資料
+------+------+
| id | name |
+------+------+
| 1 | bobu |
+------+------+
1 row in set (0.00 sec)