複製是 MySQL 的一項功能,容許服務器將更改從一個實例複製到另外一個實例。mysql
1)主服務器將全部數據和結構更改記錄到二進制日誌中。
2)從屬服務器從主服務器請求該二進制日誌並在本地應用其內容。
3)IO:請求主庫,獲取上一次執行過的新的事件,並存放到relaylog
4)SQL:從relaylog中將sql語句翻譯給從庫執行sql
1)兩臺或兩臺以上的數據庫實例
2)主庫要開啓二進制日誌
3)主庫要有複製用戶
4)主庫的server_id和從庫不一樣
5)從庫須要在開啓複製功能前,要獲取到主庫以前的數據(主庫備份,而且記錄binlog當時位置)
6)從庫在第一次開啓主從複製時,時必須獲知主庫:ip,port,user,password,logfile,pos
7)從庫要開啓相關線程:IO、SQL
8)從庫須要記錄複製相關用戶信息,還應該記錄到上次已經從主庫請求到哪一個二進制日誌
9)從庫請求過來的binlog,首先要存下來,而且執行binlog,執行過的信息保存下來數據庫
++主庫:++vim
1)主庫binlog:記錄主庫發生過的修改事件
2)dump thread:給從庫傳送(TP)二進制日誌線程緩存
++從庫:++服務器
1)relay-log(中繼日誌):存儲全部主庫TP過來的binlog事件
2)master.info:存儲複製用戶信息,上次請求到的主庫binlog位置點
3)IO thread:接收主庫發來的binlog日誌,也是從庫請求主庫的線程
4)SQL thread:執行主庫TP過來的日誌網絡
++原理++ide
1)經過change master to語句告訴從庫主庫的ip,port,user,password,file,pos
2)從庫經過start slave命令開啓複製必要的IO線程和SQL線程
3)從庫經過IO線程拿着change master to用戶密碼相關信息,鏈接主庫,驗證合法性
4)從庫鏈接成功後,會根據binlog的pos問主庫,有沒有比這個更新的
5)主庫接收到從庫請求後,比較一下binlog信息,若是有就將最新數據經過dump線程給從庫IO線程
6)從庫經過IO線程接收到主庫發來的binlog事件,存儲到TCP/IP緩存中,並返回ACK更新master.info
7)將TCP/IP緩存中的內容存到relay-log中
8)SQL線程讀取relay-log.info,讀取到上次已經執行過的relay-log位置點,繼續執行後續的relay-log日誌,執行完成後,更新relay-log.infospa
修改主庫的配置文件命令行
vim /etc/my.cnf #在[mysqld]標籤下開啓binlog和server_id log_bin=mysql-bin server_id =1
重啓數據庫(兩種方式)後進入
[root@db01 ~]# /etc/init.d/mysqld restart [root@db01 ~]# systemctl restart mysqld
查看日誌狀態
mysql> show master status; +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 120 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
建立一個複製用戶
mysql> grant replication slave on *.* to rep@'10.0.0.%' identified by '123'; Query OK, 0 rows affected (0.00 sec) mysql> show master status; #binlog pos 變成了324 +------------------+----------+--------------+------------------+-------------------+ | File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set | +------------------+----------+--------------+------------------+-------------------+ | mysql-bin.000003 | 324 | | | | +------------------+----------+--------------+------------------+-------------------+ 1 row in set (0.00 sec)
修改從庫的配置文件
vim /etc/my.cnf #在[mysqld]標籤下開啓server_id 從庫server_id不可與主庫相同,從庫之間能夠一致 server_id =2
重啓數據庫後進入執行change master to 語句
mysql> change master to master_host='10.0.0.51', #主庫ip master_user='rep', #主從複製用戶 master_password='123', #主從複製用戶密碼 master_log_file='mysql-bin.000003', #binlog master_log_pos=324, #binlog 起始點 master_port=3306; #數據庫端口
開啓slave
mysql> start slave;
查看slave狀態(yes開啓成功)
mysql> show slave status\G
查看主庫上的庫
mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | +--------------------+ 4 rows in set (0.00 sec)
建立一個新庫zeq
mysql> create database zeq; Query OK, 1 row affected (0.00 sec) mysql> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | zeq | +--------------------+ 5 rows in set (0.00 sec)
查看從庫
mysql> show databases; #從庫上已經複製過來了 +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | zeq | +--------------------+ 5 rows in set (0.01 sec)
IO線程
++鏈接主庫++
1)user password ip port
2)網絡:不通,延時高,防火牆
++請求binlog++
1)binlog不存在或者損壞
++更新relay-log和master.info++
SQL線程
1)relay-log出現問題
2)從庫作寫入了
處理方法一:
#臨時中止同步 mysql> stop slave; #將同步指針向下移動一個(可重複操做) mysql> set global sql_slave_skip_counter=1; #開啓同步 mysql> start slave;
處理方法二:
#編輯配置文件 vim /etc/my.cnf #在[mysqld]標籤下添加如下參數 slave-skip-errors=1032,1062,1007
可是以上操做都是有風險存在的
處理方法三:
1)從新備份數據庫,恢復到從庫
2)給從庫設置爲只讀
#在命令行臨時設置 mysql> set global read_only=1; #在配置文件中永久生效/etc/my.cnf read_only=1
企業中通常會延時3-6小時
延時從庫配置方法
從庫操做
#中止主從 mysql>stop slave; #設置延時爲180秒 mysql>change master to master_delay = 180; #開啓主從 mysql>start slave; #查看狀態 mysql> show slave status \G SQL_Delay: 60 3.延時從庫中止方法 #中止主從 mysql> stop slave; #設置延時爲0 mysql> CHANGE MASTER TO MASTER_DELAY = 0; #開啓主從 mysql> start slave;
主庫執行 SET GLOBAL rpl_semi_sync_master_enabled = 0; SET GLOBAL rpl_semi_sync_master_wait_no_slave = 0; 從庫執行: SET GLOBAL rpl_semi_sync_slave_enabled = 0;