數據分布
負載均衡讀操作
備份
讀寫分離
高可用和故障切換
1.2複製架構一主一從:
圖1:一主一從一主多從:
圖2:一主多從1.3主從複製的原理圖3:主從複製原理主從複製相關線程:
master節點:
dump Thread:為每個Slave的I/O Thread啟動一個dump線程,用於向其發送binary log events
slave節點:
io Thread:向master節點請求二進位日誌,並保存於中繼日誌中
sql Thread:從中繼日誌中讀取日誌事件,在本地完成重放
主從複製相關文件:
master.info:用於保存slave連接至master時的相關信息,例如帳號、密碼、伺服器地址等
relay-log.info:保存在當前slave節點上已經複製的當前二進位日誌和本地relay log日誌的對應關係
mysql-relay-bin.00000#: 中繼日誌,保存從主節點複製過來的二進位日誌,本質就是二進位日誌
1.4實現主從複製配置1.4.1主節點配置#編輯my.cnf配置文件
vim /etc/my.cnf
[mysqld]
server-id=# #為當前節點設置一個全局唯一的ID號,取值範圍為1~4294967295
log_bin #開啟二進位日誌
#連接資料庫進行操作
#記錄下使用的二進位日誌名稱和當前二進位日誌文件的Position
mysql> show master status;
#創建有複製權限的用戶帳號
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repluser'@'HOST' IDENTIFIED BY 'replpass';
#編輯my.cnf配置文件
vim /etc/my.cnf
[mysqld]
server_id=# #為當前節點設置一個全局唯一的ID號
log-bin
read_only=ON #設置資料庫只讀,針對supper user無效
relay_log=relay-log #relay log的文件路徑,默認值hostname-relay-bin
relay_log_index=relay-log.index #默認值hostname-relay-bin.index
#連接資料庫進行操作:使用有複製權限的用戶帳號連接至主伺服器,並啟動複製線程
CHANGE MASTER TO MASTER_HOST='masterhost',
MASTER_USER='repluser',
MASTER_PASSWORD='replpass',
MASTER_LOG_FILE='上方的二進位日誌文件名稱',
MASTER_LOG_POS=上方的二進位日誌文件位置;
#開啟主從複製的命令
START SLAVE [IO_THREAD|SQL_THREAD];
#查看主從複製的狀態
SHOW SLAVE STATUS;
#主節點,編輯配置文件
[root@master ~]# cat /etc/my.cnf
[mysqld]
server-id=1
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
#查看當前二進位文件信息
mysql> show master status;
+----++----+---+----+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----++----+---+----+
| master-bin.000002 | 414 | | | |
+----++----+---+----+
1 row in set (0.01 sec)
#創建複製用戶
mysql> grant replication slave on *.* to buerkeji@'192.168.10.%' identified by 'buerkeji';
Query OK, 0 rows affected, 1 warning (0.00 sec)
#從節點配置
[root@slave src]# cat /etc/my.cnf
[mysqld]
server-id=2
log-bin
relay_log=relay-log
relay_log_index=relay-log.index
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
#連接資料庫操作
mysql> CHANGE MASTER TO MASTER_HOST='192.168.10.29',
-> MASTER_USER='buerkeji',
-> MASTER_PASSWORD='buerkeji',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='master-bin.000002',
-> MASTER_LOG_POS=414;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
#開始複製
mysql> start slave;
Query OK, 0 rows affected (0.00 sec)
#查看複製狀態
mysql> show slave status\G;
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.29
Master_User: tjbool
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000002
Read_Master_Log_Pos: 710
Relay_Log_File: relay-log.000002
Relay_Log_Pos: 617
Relay_Master_Log_File: master-bin.000002
Slave_IO_Running: Yes #兩個yes即為正常工作
Slave_SQL_Running: Yes
測試
在master節點新建一個庫,看slave節點是否會自動同步
#master
mysql> create database buerkeji;
Query OK, 1 row affected (0.00 sec)
#slave,可以看到已經同步成功
mysql> show databases;
++
| Database |
++
| information_schema |
| mysql |
| performance_schema |
| sys |
| tjbool |
++
5 rows in set (0.00 sec)
#先看master節點是有數據的
mysql> use hellodb;
Database changed
mysql> show tables;
+----+
| Tables_in_hellodb |
+----+
| classes |
| coc |
| courses |
| scores |
| students |
| teachers |
| toc |
+----+
7 rows in set (0.00 sec)
mysql> select * from students;
+--+++---+----+-+
| StuID | Name | Age | Gender | ClassID | TeacherID |
+--+++---+----+-+
| 1 | Shi Zhongyu | 22 | M | 2 | 3 |
| 2 | Shi Potian | 22 | M | 1 | 7 |
| 3 | Xie Yanke | 53 | M | 2 | 16 |
| 4 | Ding Dian | 32 | M | 4 | 4 |
| 5 | Yu Yutong | 26 | M | 3 | 1 |
| 6 | Shi Qing | 46 | M | 5 | NULL |
| 7 | Xi Ren | 19 | F | 3 | NULL |
| 8 | Lin Daiyu | 17 | F | 7 | NULL |
| 9 | Ren Yingying | 20 | F | 6 | NULL |
| 10 | Yue Lingshan | 19 | F | 3 | NULL |
| 11 | Yuan Chengzhi | 23 | M | 6 | NULL |
| 12 | Wen Qingqing | 19 | F | 1 | NULL |
| 13 | Tian Boguang | 33 | M | 2 | NULL |
| 14 | Lu Wushuang | 17 | F | 3 | NULL |
| 15 | Duan Yu | 19 | M | 4 | NULL |
| 16 | Xu Zhu | 21 | M | 1 | NULL |
| 17 | Lin Chong | 25 | M | 4 | NULL |
| 18 | Hua Rong | 23 | M | 7 | NULL |
| 19 | Xue Baochai | 18 | F | 6 | NULL |
| 20 | Diao Chan | 19 | F | 7 | NULL |
| 21 | Huang Yueying | 22 | F | 6 | NULL |
| 22 | Xiao Qiao | 20 | F | 1 | NULL |
| 23 | Ma Chao | 23 | M | 4 | NULL |
| 24 | Xu Xian | 27 | M | NULL | NULL |
| 25 | Sun Dasheng | 100 | M | NULL | NULL |
+--+++---+----+-+
25 rows in set (0.00 sec)
#首先將master節點數據進行一次全量備份
[root@master data]# mysqldump -p -A -F --single-transaction --master-data=1 > /data/fullbackup.sql
#將該文件copy到slave節點,並且配置該文件,指定從完全備份的位置之後開始複製
[root@localhost src]# vim fullbackup.sql
CHANGE MASTER TO
MASTER_HOST='192.168.10.29',
MASTER_USER='buerkeji',
MASTER_PASSWORD='buerkeji',
MASTER_PORT=3306,
#以下內容為文件自帶,無需更改
MASTER_LOG_FILE='master-bin.000003', MASTER_LOG_POS=154;
#導入
[root@localhost src]# mysql < fullbackup.sql -p
#開啟同步
mysql> start slave;
#查看同步狀態
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.10.29
Master_User: tjbool
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: master-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: localhost-relay-bin.000002
Relay_Log_Pos: 321
Relay_Master_Log_File: master-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
需要將腳本與MySQL的安裝包放在同一個目錄下,可以任意指定MySQL版本,只需在腳本中更改變量值即可。
#!/bin/bash
. /etc/init.d/functions
SRC_DIR=`pwd`
MYSQL='mysql-5.7.29-linux-glibc2.12-x86_64.tar.gz'
COLOR='echo -e \E[01;31m'
END='\E[0m'
#你的MySQL密碼
MYSQL_ROOT_PASSWORD="buerkeji"
check (){
if [ $UID -ne 0 ]; then
action "當前用戶不是root,安裝失敗" false
exit 1
fi
cd $SRC_DIR
if [ ! -e $MYSQL ];then
$COLOR"缺少${MYSQL}文件"$END
$COLOR"請將相關軟體放在${SRC_DIR}目錄下"$END
exit
elif [ -e /usr/local/mysql ];then
action "資料庫已存在,安裝失敗" false
exit
else
return
fi
}
install_mysql(){
$COLOR"開始安裝MySQL資料庫..."$END
yum -y -q install libaio numactl-libs libaio &> /dev/null
cd $SRC_DIR
tar xf $MYSQL -C /usr/local/
MYSQL_DIR=`echo $MYSQL| sed -nr 's/^(.*[0-9]).*/\1/p'`
ln -s /usr/local/$MYSQL_DIR /usr/local/mysql
chown -R root.root /usr/local/mysql/
id mysql &> /dev/null || { useradd -s /sbin/nologin -r mysql ; action "創建mysql用戶"; }
echo 'PATH=/usr/local/mysql/bin/:$PATH' > /etc/profile.d/mysql.sh
. /etc/profile.d/mysql.sh
ln -s /usr/local/mysql/bin/* /usr/bin/
cat > /etc/my.cnf <<-EOF
[mysqld]
server-id=1
log-bin
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
[client]
socket=/data/mysql/mysql.sock
EOF
mysqld --initialize --user=mysql --datadir=/data/mysql
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
chkconfig --add mysqld
chkconfig mysqld on
service mysqld start
[ $? -ne 0 ] && { $COLOR"資料庫啟動失敗,退出!"$END;exit; }
MYSQL_OLDPASSWORD=`awk '/A temporary password/{print $NF}' /data/mysql/mysql.log`
mysqladmin -uroot -p$MYSQL_OLDPASSWORD password $MYSQL_ROOT_PASSWORD &>/dev/null
action "資料庫安裝完成"
}
check
install_mysql
[root@cdh-mysql log]# cat /etc/my.cnf
[mysqld]
server-id=1
#設置唯一的server-id
log-bin=cdh-mysql-bin
#開啟二進位日誌,並指定日誌名稱
binlog_format=row
#指定二進位日誌格式
binlog_cache_size = 4M
max_binlog_cache_size = 8M
max_binlog_size = 512M
#期待二進位日誌保存的天數
expire_logs_days = 7
#大小寫不區分
lower_case_table_names=1
key_buffer_size = 2048M
default_time_zone = "+8:00"
datadir=/data/mysql
socket=/data/mysql/mysql.sock
log-error=/data/mysql/mysql.log
pid-file=/data/mysql/mysql.pid
tmpdir = /tmp/mysql
back_log = 600
#back_log 是作業系統在監聽隊列中所能保持的連接數
log_timestamps=SYSTEM
#設置MySQL的日誌為系統時間
max_connections = 3000
#MySQL的最大連接數量
max_connect_errors = 1500
#每個客戶端連接最大的錯誤允許數量,當超過該次數,MYSQL伺服器將禁止此主機的連接請求,直到MYSQL伺服器重啟或通過flush hosts命令清空此主機的相關信息
external-locking = FALSE
#使用–skip-external-locking MySQL選項以避免外部鎖定。
max_allowed_packet = 32M
#每個連接傳輸數據大小.最大1G,須是1024的倍數,一般設為最大的BLOB的值
sort_buffer_size = 8M
# 排序緩衝被用來處理類似ORDER BY以及GROUP BY隊列所引起的排序
join_buffer_size = 8M
#不帶索引的全表掃描.使用的buffer的最小值
thread_cache_size = 300
# 伺服器線程緩存這個值表示可以重新利用保存在緩存中線程的數量,當斷開連接時如果緩存中還有空間,那麼客戶端的線程將被放到緩存中,如果線程重新被請求,那麼請求將從緩存中讀取,如果緩存中是空的或者是新的請求,那麼這個線程將被重新創建,如果有很多新的線程,增加這個值可以改善系統性能.通過比較 Connections 和 Threads_created 狀態的變量,可以看到這個變量的作用。設置規則如下:1GB 內存配置為8,2GB配置為16,3GB配置為32,4GB或更高內存,可配置更大。
query_cache_size = 64M
#查詢緩衝大小
query_cache_limit = 4M
#指定單個查詢能夠使用的緩衝區大小,預設為1M
query_cache_min_res_unit = 2k
#默認是4KB,設置值大對大數據查詢有好處,但如果你的查詢都是小數據查詢,就容易造成內存碎片和浪費
default_storage_engine= InnoDB
#默認使用InnoDB作為存儲引擎
thread_stack = 192K
#設置MYSQL每個線程的堆棧大小,默認值足夠大,可滿足普通操作。可設置範圍為128K至4GB,默認為192KB。
character_set_server=utf8mb4
#設置默認字符集為utf8mb4
transaction_isolation = READ-COMMITTED
# 設定默認的事務隔離級別.可用的級別如下:
# READ-UNCOMMITTED, READ-COMMITTED, REPEATABLE-READ, SERIALIZABLE
# 1.READ UNCOMMITTED-讀未提交2.READ COMMITTE-讀已提交3.REPEATABLE READ -可重複讀4.SERIALIZABLE -串行
slow_query_log = 1
#開啟慢查詢日誌記錄
innodb_buffer_pool_size = 10G
#InnoDB使用一個緩衝池來保存索引和原始數據, 可設置這個變量到物理內存大小的80%
innodb_thread_concurrency = 16
#在InnoDb核心內的允許線程數量,建議的設置是CPU數量加上磁碟數量的兩倍
innodb_flush_log_at_trx_commit = 2
# 如果將此參數設置為1,將在每次提交事務後將日誌寫入磁碟。為×××能,可以設置為0或2,但要承擔在發生故障時丟失數據的風險。設置為0表示事務日誌寫入日誌文件,而日誌文件每秒刷新到磁碟一次。設置為2表示事務日誌將在提交時寫入日誌,但日誌文件每次刷新到磁碟一次。
innodb_log_buffer_size = 16M
#此參數確定日誌文件所用的內存大小,以M為單位。緩衝區更大能提高性能,但意外的故障將會丟失數據.MySQL開發人員建議設置為1-8M之間
innodb_log_file_size = 128M
#此參數確定數據日誌文件的大小,以M為單位,更大的設置可以提高性能,但也會增加恢復故障資料庫所需的時間
innodb_log_files_in_group = 3
#在日誌組中的文件總數
innodb_max_dirty_pages_pct = 90
# Buffer_Pool中Dirty_Page所佔的數量,直接影響InnoDB的關閉時間。參數innodb_max_dirty_pages_pct 可以直接控制了Dirty_Page在Buffer_Pool中所佔的比率,而且幸運的是innodb_max_dirty_pages_pct是可以動態改變的。所以,在關閉InnoDB之前先將innodb_max_dirty_pages_pct調小,強制數據塊Flush一段時間,則能夠大大縮短 MySQL關閉的時間。
innodb_lock_wait_timeout = 120
# InnoDB 有其內置的死鎖檢測機制,能導致未完成的事務回滾。但是,如果結合InnoDB使用MyISAM的lock tables 語句或第三方事務引擎,則InnoDB無法識別死鎖。為消除這種可能性,可以將innodb_lock_wait_timeout設置為一個整數值,指示 MySQL在允許其他事務修改那些最終受事務回滾的數據之前要等待多長時間(秒數)
innodb_file_per_table = 1
#打開獨立的表空間