1. 基於binlog搭建主從復制
1)、主從復制原理

- 用戶寫入數據到master數據庫中
- master數據庫數據寫入binlog文件中,通知到slave數據庫
- slave數據庫的I/O線程從master數據庫binlog讀取數據到slave數據庫的relay log中
- slave數據庫的SQL線程重放relaylog,也就是將數據還原到庫中
2)、binlog三種模式:通過命令show variables like 'binlog_format';或select @@binlog_format;可查看binlog日志模式;也可通過命令set binlog_format=STATEMENT或ROW或MIXED設置binlog模式;命令只是臨時的,重啟MySQL就會失效,永久設置需要在my.cnf的[msqld]下添加binlog_format=STATEMENT或ROW或MIXED
- statement level模式:每一條修改數據的SQL記錄到master的binlog中,這樣會減少binlog數據量,slave只需根據SQL命令就可以同步數據,但是這只限於簡單的SQL操作,如果有依賴宿主環境和復雜函數的SQL就不能正確同步數據了,如記錄宿主機機器名等;
- row level模式:master的binlog記錄每一行數據被修改的形式,slave會做同樣的修改,這樣可以避免statement level的缺點,但會帶來數據量大的問題,如一個簡單的update SQL操作,statement level就是一條SQL記錄,而row level要記錄下所有影響行的數據;
- mixed模式:會結合statement level和row level優點區分對待記錄日志形式。其實新版本的MySQL已經對row level模式做了一定優化,比如對表定義的修改就以statement level形式記錄。
3)、主從復制環境搭建:(如果有防火牆限制,可以先關閉防火牆)MySQL客戶端可以是docker內登錄或者其他連接MySQL的客戶端
a. 主服務器配置如下:
- 開啟binlog,MySQL8.0默認開啟,可通過命令show variables like 'log_bin%';查看到log_bin為ON;如果默認為OFF,即關閉,需要在my.cnf的[msqld]下添加log_bin=mybinlog,mybinlog可以自定義修改,為binlog的basename;
- 設置server_id,在my.cnf的[msqld]下添加server_id=3316,保證集群中唯一;我本地用docker環境,配置的server_id為對外暴露的端口號;
- 在配置文件修改完log_bin和server_id后,啟動鏡像容器,成功后,可在數據文件下看到mybinlog.index文件,里面記錄的是mybinlog文件位置,可直接使用cat命令查看,而查看binlog文件需要使用mysql工具命令:docker exec -it mysqlmaster mysqlbinlog --no-defaults --base64-output=decode-rows /var/lib/mysql/mybinlog.000001,--no-defaults參數是解決mysqlbinlog: [ERROR] unknown variable 'default-character-set=utf8mb4';
docker run --name mysqlmaster -p 3316:3306 --privileged=true -v /root/mysqlmaster/conf:/etc/mysql/conf.d -v /root/mysqlmaster/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0
- 在mysql客戶端創建一個用戶,用於slave中配置連接master,同步數據,同時授予該用戶備份數據權限;如果不想創建新用戶可直接用root,賦予備份數據權限即可;
create user 'rep'@'%' identified by '@Rep123'; grant replication slave on *.* to 'rep'@'%';
- 在mysql客戶端執行刷新權限命令:flush privileges;
- 在mysql客戶端查看master狀態,命令:show master status; ,記錄file和position,要用到slave配置中;如file為mybinlog.000003,position為896
b. 從服務器配置如下:
- 設置server_id,在my.cnf的[msqld]下添加server_id=3326,保證集群中唯一;我本地用docker環境,配置的server_id為對外暴露的端口號;
- 配置完后啟動鏡像容器
docker run --name mysqlslave -p 3326:3306 --privileged=true -v /root/mysqlslave/conf:/etc/mysql/conf.d -v /root/mysqlslave/data:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=root -d mysql:8.0
- 將master中現有數據手動遷移到slave,如果是全新的庫,可忽略此步
- 在mysql客戶端執行如下命令,指定slave的master信息
change master to master_host='10.0.79.61', master_port=3316, master_user='rep', master_password='@Rep123', master_log_file='mybinlog.000004', master_log_pos=156, MASTER_AUTO_POSITION=0;
- 在mysql客戶端啟動從服務器復制功能:start slave;
- 在mysql客戶端執行命令:show slave status;查看從庫是否正常,可觀察Slave_IO_Running和Slave_SQL_Running值都為Yes即可
c. 測試(本地測試通過):
- 在主庫中執行創建數據庫:create database dbtest;use dbtest;
- 創建表
CREATE TABLE `test` ( `id` bigint NOT NULL AUTO_INCREMENT, `a` bigint DEFAULT NULL, `b` bigint DEFAULT NULL, `c` bigint DEFAULT NULL, `d` varchar(100) DEFAULT NULL, PRIMARY KEY (`id`), KEY `idx_a_b_c` (`a`,`b`,`c`) USING BTREE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
- 插入數據,查看從庫,同步成功。
d. 清理binlog方式:
- 手動清理:按照時間清理命令purge master logs before '2022-01-01 17:20:00';或按照文件索引清理purge master logs to'mybinlog.000022';
- 自動清理,設置binlog過期時間:expire_logs_days=7,單位天
2. 基於主從復制的高可用方案,可設計如下,准備兩個雙主節點的數據庫,也就是互相做主從復制,通過keepalive工具實現高可用

3. 基於MySQL-Proxy搭建讀寫分離
MySQL官方不推薦用於生產,所以做贅述
4. MySQL Router搭建MySQL集群
實際工作中用的並不多,生產上用的都是MySQL中間件,如當當的sharding-jdbc,蘑菇街的TSharding,奇虎360的Atlas,阿里的Cobar,阿里基於Cobar的MyCAT,58同城的Oceanus,谷歌的Vitess
5. 生產用的分庫分表后期通過ShardingSphere進行講解和實現
