mariadb/mysql主從複製
一、mysql的複製原理
至少需要兩個節點,一主(master)一從(slave)
那麼從節點如何從主節點獲得數據呢?
1、主節點開啓二進制日誌,記錄了修改數據的所有語句
2、從節點扮演mysql客戶端請求主節點的二進制日誌,默認是第一個文件的最開始位置,通常要指定二進制文件的指定位置。從節點收到二進制日誌後保存在本地的中繼日誌中,並且會記錄已經讀取到哪個二進制日誌的哪個位置,用作再次請求二進制日誌的起始位置。從節點會讀取中繼日誌中的事件完成重放後從而形成一模一樣的數據保存在數據庫中。
3、slave節點上負責從master節點上請求二進制日誌的線程叫做IO_THREAD,從節點收到二進制日誌後,保存在本地中繼日誌中並由SQL_THREAD做重放後將數據保存在數據庫中。
4、主節點會爲每個請求二進制日誌的從服務器線程IO_THREAD啓動一個響應線程dump_thread,該線程負責讀取主服務器上的二進制日誌併發送給從服務器。
二、mysql基於二進制日誌主從複製特點:
1、異步複製
當客戶端寫入數據時,主節點記錄完二進制日誌便回覆客戶端已經寫好了,而無需等待從節點寫入完成纔回復。因此,數據剛剛在主服務器上寫入完成,而沒有來得及同步到從節點的話,從服務器上是讀取不到該數據的。
2、從節點可能會落後於主節點/主從數據不一致
有時候,落後也是有好處的,萬一主服務器上誤刪了數據,從服務器上還是可以保留一段時間的。可以專門部署一臺服務器落後於主節點的。
主節點上,事務是可以並行執行提交的,但是二進制日誌還是隻能串行寫入的,而等到從節點過來讀取二進制日誌並完成重放以後,就必然是落後了。
根據經驗:同一機房內,主從之間最多落後1秒,可以接受
問題一:從節點上的中繼日誌完成重放後需要保留嗎?
不需要,SQL_THREAD把中繼日誌重放完了以後
問題二:從節點上需要保存二進制日誌嗎?
需要看情況而定
1、二進制日誌是用來發給從服務器做事件重放使用,所以從服務器如果沒有從服務器的話,是不需要保留二進制日誌的,因爲保存二進制日誌會增加了IO壓力。
2、如果mysql從服務器擁有自己的從服務器,這種架構就是mysql的級聯複製
補充知識點
二進制日誌的事件記錄格式:
STATEMENT:只記錄修改的語句,雖然節省空間但不推薦,極有可能導致數據不一致
ROW:記錄被修改的行的數據,記錄數據最精確,需要更多存儲空間,推薦
MIXED:默認的記錄格式,mysql自行判定以STATEMENT還是ROW的方式來記錄,推薦
三、主從複製模型配置過程演示
主節點:開啓二進制日誌,設定全局唯一的SERVER_ID,創建擁有複製權限的用戶賬號(需要REPLICATION SLAVE,REPLICATION CLIENT)
從節點:開啓中繼日誌,設定全局唯一的SERVER_ID,使用有複製權限的用戶賬號連接至主服務器並啓動複製線程
node1: 172.16.92.1/16 mariadb主服務器
node2: 172.16.92.2/16 mariadb從服務器
以上節點均爲CentOS 7.1
配置環境
1. 配置好光盤yum源
2. 關閉selinux和iptables
node1: mariadb主服務器 [root@node1 ~]# yum -y install mariadb-server [root@node1 ~]# vim /etc/my.cnf [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 # Settings user and group are ignored when systemd is used. # If you need to run mysqld under a different user or group, # customize your systemd unit file for mariadb according to the # instructions in http://fedoraproject.org/wiki/Systemd #######以下的內容爲添加######## #二進制變更日誌 log-bin=mysql-bin #二進制日誌格式爲混合模式 binlog_format=mixed #爲主服務器node1的ID值 server-id = 1 port = 3306 skip-external-locking key_buffer_size = 256M max_allowed_packet = 1M table_open_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size= 16M thread_concurrency = 4 innodb_file_per_table = on skip_name_resolve = on ############################### ###### 以下的內容可選 ######## [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash [myisamchk] key_buffer_size = 128M sort_buffer_size = 128M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout ############################# [mysqld_safe] log-error=/var/log/mariadb/mariadb.log pid-file=/var/run/mariadb/mariadb.pid # # include all files from the config directory # !includedir /etc/my.cnf.d ############### End for my.cnf ################# [root@node1 ~]# systemctl start mariadb [root@node1 ~]# mysql MariaDB [(none)]> grant replication client,replication slave on *.* to 'repluser'@'172.16.92.2' identified by 'replpass'; MariaDB [(none)]> flush privileges; MariaDB [(none)]> show master status\G *************************** 1. row *************************** File: mysql-bin.000003 Position: 497 Binlog_Do_DB: Binlog_Ignore_DB: ##### 記下mysql-bin.000003 和 497 , 設置從服務器中繼日誌時有用 #### node2: mariadb從服務器 [root@node2 ~]# yum -y install mariadb-server [root@node2 ~]# vim /etc/my.cnf [mysqld] datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock # Disabling symbolic-links is recommended to prevent assorted security risks symbolic-links=0 # Settings user and group are ignored when systemd is used. # If you need to run mysqld under a different user or group, # customize your systemd unit file for mariadb according to the # instructions in http://fedoraproject.org/wiki/Systemd ########## 添加以下內容 ########## log-bin=mysql-bin binlog_format=mixed server-id = 2 relay-log = relay-bin log_slave_updates = 1 read_only = on port = 3306 skip-external-locking key_buffer_size = 256M max_allowed_packet = 1M table_open_cache = 256 sort_buffer_size = 1M read_buffer_size = 1M read_rnd_buffer_size = 4M myisam_sort_buffer_size = 64M thread_cache_size = 8 query_cache_size= 16M thread_concurrency = 4 innodb_file_per_table = on skip_name_resolve = on ################################### ######### 以下內容可選 ############ [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash [myisamchk] key_buffer_size = 128M sort_buffer_size = 128M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout #################################### [mysqld_safe] log-error=/var/log/mariadb/mariadb.log pid-file=/var/run/mariadb/mariadb.pid # # include all files from the config directory # !includedir /etc/my.cnf.d ############# End of my.cnf ############### [root@node2 ~]# systemctl start mariadb [root@node2 ~]# mysql MariaDB [(none)]> show global variables like '%read_only%'; | read_only | ON | MariaDB [(none)]> show global variables like '%read_only%'\G *************************** 1. row *************************** Variable_name: read_only Value: ON MariaDB [(none)]> change master to master_host='172.16.92.1',master_user='repluser',master_password='replpass',master_log_file='mysql-bin.000003',master_log_pos=497,master_connect_retry=5,master_heartbeat_period=2; MariaDB [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Master_Host: 172.16.92.1 Master_User: repluser Master_Port: 3306 Connect_Retry: 5 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 497 Relay_Log_File: relay-bin.000001 Relay_Log_Pos: 4 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: No Slave_SQL_Running: No Replicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0 Last_Error: Skip_Counter: 0 Exec_Master_Log_Pos: 497 Relay_Log_Space: 245 Until_Condition: None Until_Log_File: Until_Log_Pos: 0 Master_SSL_Allowed: No Master_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: NULL Master_SSL_Verify_Server_Cert: No Last_IO_Errno: 0 Last_IO_Error: Last_SQL_Errno: 0 Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 0 MariaDB [(none)]> start slave; MariaDB [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.92.1 Master_User: repluser Master_Port: 3306 Connect_Retry: 5 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 497 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 529 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes ........ 其餘信息略 ........ MariaDB [(none)]> show processlist\G *************************** 3. row *************************** Id: 4 User: system user Host: db: NULL Command: Connect Time: 144 State: Slave has read all relay log; waiting for the slave I/O thread to update it Info: NULL Progress: 0.000 #說明: 從節點已經接收到所有的中繼日誌 node1 主節點上可查看到此進程 MariaDB [(none)]> show processlist\G *************************** 2. row *************************** Id: 4 User: repluser Host: 172.16.92.2:56821 db: NULL Command: Binlog Dump Time: 212 State: Master has sent all binlog to slave; waiting for binlog to be updated Info: NULL Progress: 0.000 在主節點上創建數據庫測試是否能主從同步 MariaDB [(none)]> create database testdb; 在從節點上可看到testdb數據庫, 說明主從同步成功! MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 再來看一下 從節點 的狀態 MariaDB [(none)]> show slave status\G *************************** 1. row *************************** Slave_IO_State: Waiting for master to send event Master_Host: 172.16.92.1 Master_User: repluser Master_Port: 3306 Connect_Retry: 5 Master_Log_File: mysql-bin.000003 Read_Master_Log_Pos: 584 #497->584 Relay_Log_File: relay-bin.000002 Relay_Log_Pos: 616 #529->616 Relay_Master_Log_File: mysql-bin.000003 Slave_IO_Running: Yes Slave_SQL_Running: Yes ############# mysql主從複製結束 ############## 複製過濾器 (1) 基於庫的白名單的實現 在從節點上設置 MariaDB [(none)]> stop slave; MariaDB [(none)]> set global replicate_do_db='testdb'; MariaDB [(none)]> start slave; MariaDB [(none)]> show global variables like '%replicat%'; | replicate_do_db | testdb | #只同步該數據庫的數據 在主節點上創建新數據庫, 查看是否能同步過來 MariaDB [(none)]> create database mydb; 從節點上並未看到mydb數據庫 MariaDB [(none)]> show databases; +--------------------+ | Database | +--------------------+ | information_schema | | mysql | | performance_schema | | test | | testdb | +--------------------+ 在主節點的testdb中插入數據, 查看是否能同步過來 MariaDB [(none)]> use testdb; MariaDB [testdb]> create table t1(id int); MariaDB [testdb]> desc t1\G *************************** 1. row *************************** Field: id Type: int(11) Null: YES Key: Default: NULL Extra: 從節點上查看一樣的數據, 說明從服務器現在只能同步一個數據庫 MariaDB [(none)]> use testdb; MariaDB [testdb]> show tables\G *************************** 1. row *************************** Tables_in_testdb: t1 MariaDB [testdb]> desc t1\G *************************** 1. row *************************** Field: id Type: int(11) Null: YES Key: Default: NULL Extra: