1. 程式人生 > 其它 >第二十九節 MySQL資料庫企業級應用實踐

第二十九節 MySQL資料庫企業級應用實踐

第二十九節 MySQL資料庫企業級應用實踐

一,概述

1.1 MySQL介紹

MySQL屬於傳統關係型資料庫產品,它開放式的架構使得使用者選擇性很強,同時社群開發與維護人數眾多。其功能穩定,效能卓越,且在遵守GPL協議的前提下,可以免費使用與修改,也為MySQL的推廣與使用帶來了更多的利好。在MySQL成長與發展過程中,支援的功能逐漸增多,效能也不斷提高,對平臺的支援也越來越多。
MySQL是一種關係型資料庫管理系統,關係型資料庫的特點是將資料儲存在不同的表中,再將這些表放入不同的資料庫中,而不是將所有資料統一放在一個大倉庫裡,這樣的設計增加了MySQL的讀取速度,而且靈活性和可管理性也得到了很大提高。訪問及管理MySQL資料庫的最常用標準化語言為SQL結構化查詢語言。

1.2 MariaDB 資料庫的誕生背景介紹

自甲骨文公司收購MySQL後,其在商業資料庫與開源資料庫領域市場的佔有份額都躍居第一,這樣的格局引起了業內很多的人士的擔憂,因為商業資料庫的老大有可能將MySQL閉源。為了避免Oracle將MySQL閉源,而無開源的類MySQL資料庫可用,MySQL社群採用分支的方式來避開這個風險。MariaDB資料庫就這樣誕生了,MariaDB是一個向後相容,可能在以後替代MySQL的資料庫產品,其官方地址為:https://mariadb.org/ 。不過,這裡還是建議大家選擇更穩定,使用更廣泛的MySQL資料庫,可以先測試MariaDB資料庫,等使用的人員更多一些,社群更活躍後再考慮使用為好。

二,MySQL多例項介紹

在之前LNMP的講解中,已經針對MySQL資料庫進行了介紹,並說明了為什麼要選擇MySQL資料庫,以及MySQL資料庫在Linux系統下的多種安裝方式,同時講解了MySQL的二進位制方式單例項安裝,基礎優化等內容,本節將為同學們講解更為實用的MySQL多例項安裝,主從複製叢集等重要應用實踐。

2.1 什麼是MySQL多例項

  • 簡單的說,MySQL多例項就是在一臺伺服器上同時開啟多個不同的伺服器埠(如:3306,3307),同時執行多個MySQL服務程序,這些服務程序通過不同的socket監聽不同的伺服器埠來提供服務。
  • 這些MySQL多例項共用一套MySQL安裝程式,使用不同的my.cnf(也可以相同)配置檔案,啟動程式(也可以相同)和資料檔案。在提供服務時,多例項MySQL在邏輯上看起來是各自獨立的,它們根據配置檔案的對應設定值,獲得伺服器相應數量的硬體資源。
  • 打個比方吧,MySQL多例項就相當於房子的多個臥室,每個例項可以看作一間臥室,整個伺服器就是一套房子,伺服器的硬體資源(CPU,Mem,Disk),軟體資源(Centos作業系統)可以看作房子的衛生間,廚房,客廳,是房子的公用資源。
  • 其實很多網路服務都是可以配置多例項的,例如Nginx,Apache,Haproxy,Redis,Memcache等。這在入口網站使用得很廣泛。

2.2 MySQL多例項的作用與問題

MySQL多例項的作用如下:

(1)有效利用伺服器資源

當單個伺服器資源有剩餘時,可以充分利用剩餘的資源提供更多的服務,且可以實現資源的邏輯隔離。

(2)節約伺服器資源

當公司資金緊張,但是資料庫又需要各自盡量獨立地提供服務,而且,需要主從複製等技術時,多例項就再好不過了。

MySQL多例項有它的好處,但也有其弊端,比如,會存在資源互相搶佔的問題。

當某個資料庫例項併發很高或有SQL慢查詢時,整個例項會消耗大量的系統CPU,磁碟I/O等資源,導致伺服器上的其他資料庫例項提供服務的質量一起下降。這就相當於大家住在一個房子的不同臥室一樣,早晨起來上班,都要刷牙,洗臉等,這樣衛生間就會長期佔用,其他人要等待一樣。不同例項獲取的資源是相對獨立的,無法像虛擬化一樣完全隔離。

三, MySQL多例項的生產應用場景

3.1 資金緊張型公司的選擇

若公司資金緊張,公司業務訪問量不太大,但又希望不同業務的資料庫服務各自盡量獨立地提供服務而互相不受影響,同時,還需要主從複製等技術提供備份或讀寫分離服務,那麼多例項就再好不過了。例如:可以通過3臺伺服器部署9~15個例項,交叉做主從複製,資料備份及讀寫分離,這樣就可達到9~15臺伺服器每個只裝一個數據庫才有的效果。這裡要強調的是,所謂的儘量獨立是相對的。

3.2 併發訪問不是特別大的業務

當公司業務訪問量不太大的時候,伺服器的資源基本上都浪費了,這時就很適合多例項的應用,如果對SQL語句的優化做得比較好,MySQL多例項會是一個很值得使用的技術,即使併發很大,合理分配好系統資源,搭配好服務,也不會有太大問題。

3.3 入口網站應用MySQL多例項場景

入口網站通常都會使用多例項,因為配置硬體好的伺服器,可節省IDC機櫃空間,同時,跑多例項也會減少硬體資源跑不滿的浪費。比如,百度公司的很多資料庫都是多例項,不過,一般是從庫多例項,例如某部門中使用的IBM伺服器為48核CPU,記憶體96GB,一臺伺服器跑3~4個例項;此外,新浪網使用的也是多例項,記憶體48GB左右。

說明:

據調查,新浪網的資料庫單機1~4個數據庫例項的居多,其中又數1~2個的最多,因為大業務佔用的機器比較多。伺服器是DELL R510的居多,CPU是E5210,48GB記憶體,磁碟12×300G SAS,做RAID10,此為入口網站的伺服器配置參考,希望能給同學們的面試帶來一些啟迪。

另外,新浪網站安裝資料庫時,一般採用編譯安裝的方式,並且會在優化之後做成rpm包,以便統一使用。

四, MySQL多例項常見的配置方案

4.1 單一配置檔案,單一啟動程式的多例項部署方案

下面是MySQL官方文件提到的單一配置檔案,單一啟動程式多例項部署方案,但不推薦此方案,這裡僅作為知識點提及,後文不再涉及此方案的說明。my.cnf配置檔案示例(MySQL手冊裡提到的方法)如下:

[mysqld_multi]
mysqld      =   /usr/bin/mysqld_safe
mysqladmin  =   /usr/bin/mysqladmin
user        =   mysql
[mysqld1]
socket      =   /var/lib/mysql/mysql.sock
port        =   3306
pid-file    =   /var/lib/mysql/mysql.pid
datadir     =   /var/lib/mysql/
user        =   mysql
[mysqld2]
socket      =   /mnt/data/db1/mysql.sock
port        =   3302
pid-file    =   /mnt/data/db1/mysql.pid
datadir     =   /mnt/data/db1/
user        =   mysql
skip-name-resolv
server-id=10
default-storage-engine=innodb
innodb_buffer_pool_size=512M
innodb_additional_mem_pool=10M
default_character_set=utf8
character_set_server=utf8
#read-only
relay-log-space-limit=3G
expire_logs_day=20

啟動程式的命令如下:

mysqld_multi --config-file=/data/mysql/my_multi.cnf start 1,2

該方案的缺點是耦合度太高,一個配置檔案,不好管理。工作開發和運維的統一原則為降低耦合度。

4.2 多配置檔案,多啟動程式的部署方案

多配置檔案,多啟動程式部署方案,是本文主要講解的方案,也是非常常用並極力推薦的多例項方案。下面來看配置示例。

[root@localhost /]# tree /data
/data
├── 3306
├── data        #3306例項的資料目錄
├── my.cnf      #3306例項的配置檔案
└── mysql       #3306例項的啟動檔案
└── 3307
    ├── data        #3307例項的資料目錄
    ├── my.cnf      #3307例項的配置檔案
    └── mysql       #3307例項的啟動檔案

4 directories, 4 files

提示:
這裡的配置檔案my.cnf,啟動程式mysql都是獨立的檔案,資料檔案data目錄也是獨立的。
多例項MySQL資料庫的安裝和之前講解的單例項沒有任何區別,因此,同學們如果有前文單例項的安裝環境,那麼可以直接略過5.1節的內容。

五,安裝並配置多例項MySQL資料庫

5.1 安裝MySQL多例項

1,安裝MySQL需要的依賴包和編譯軟體

(1)安裝MySQL需要的依賴包

安裝MySQL之前,最好先安裝MySQL需要的依賴包,不然後面會出現很多報錯資訊,到那時還得再回來安裝MySQL的依賴包。安裝命令如下:

[root@localhost ~]# yum -y install ncurses-devel libaio-devel
[root@localhost ~]# rpm -qa ncurses-devel libaio-devel
ncurses-devel-5.7-4.20090207.el6.x86_64
libaio-devel-0.3.107-10.el6.x86_64

(2)安裝編譯MySQL需要的軟體

首先通過網路獲得cmake軟體,然後進行如下操作:

[root@localhost ~]# ls -lh cmake-2.8.6.tar.gz 
-rw-r--r-- 1 root root 5.4M 7月  19 20:43 cmake-2.8.6.tar.gz          #此軟體需提前準備
[root@localhost ~]# tar xf cmake-2.8.6.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/cmake-2.8.6/
[root@localhost cmake-2.8.6]# ./configure
[root@localhost cmake-2.8.6]# gmake && gmake install
[root@localhost cmake-2.8.6]# which cmake

2,開始安裝MySQL

為了讓同學們學習更多的MySQL技術,接下來會以相對複雜的原始碼安裝來講解MySQL多例項的安裝。大型公司一般都會將MySQL軟體定製成rpm包,然後放到yum倉庫裡,使用yum安裝,中小企業裡的二進位制和編譯安裝的區別不大。

(1)建立MySQL使用者賬號

首先以root身份登入到Linux系統中,然後執行如下命令建立mysql使用者賬號:

[root@localhost ~]# useradd -s /sbin/nologin -M mysql
[root@localhost ~]# id mysql
uid=500(mysql) gid=500(mysql) 組=500(mysql)

(2)獲取MySQL軟體包

MySQL軟體包的下載地址為:https://dev.mysql.com/downloads/mysql/
提示:
本例以MySQL編譯的方式來講解,之前已經演示過二進位制方式安裝了。在生產場景中,二進位制和原始碼包兩種安裝方法都是可以用的,其應用場景一般沒什麼差別。不同之處在於,二進位制的安裝包較大,名字和原始碼包也有些區別,二進位制安裝過程比原始碼更快。

MySQL原始碼包和二進位制安裝包的名稱見下圖

(3)採用編譯方式安裝MySQL

配置及編譯安裝的步驟如下:

[root@localhost ~]# tar xf mysql-5.5.22.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/mysql-5.5.22/
[root@localhost mysql-5.5.22]# cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-5.5.22 \
> -DMYSQL_DATADIR=/usr/local/mysql-5.5.22/data \        #資料存放目錄
> -DMYSQL_UNIX_ADDR=/usr/local/mysql-5.5.22/tmp/mysql.sock \    #MySQL程序間通訊的套接字位置
> -DDEFAULT_CHARSET=utf8 \                  #預設字符集為utf8
> -DDEFAULT_COLLATION=utf8_general_ci \     #預設字符集排序規則
> -DEXTRA_CHARSETS=gbk,gb2312,utf8,ascii \  #額外的字符集支援
> -DENABLED_LOCAL_INFILE=ON \               #是否啟用載入本地資料
> -DWITH_INNOBASE_STORAGE_ENGINE=1 \        #靜態編譯innodb儲存引擎到資料庫
> -DWITH_FEDERATED_STORAGE_ENGINE=1 \       #靜態編譯FEDERATED儲存引擎到資料庫
> -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \       #靜態編譯blackhole儲存引擎到資料庫
> -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 \      #不編譯EXAMPLE儲存引擎到資料庫
> -DWITHOUT_PARTITION_STORAGE_ENGINE=1 \    #不支援資料庫分割槽
> -DWITH_FAST_MUTEXES=1 \
> -DWITH_ZLIB=bundled \                     #zlib壓縮模式
> -DENABLED_LOCAL_INFILE=1 \                #是否啟用本地的LOCAL_INFILE
> -DWITH_READLINE=1 \                       #使用捆綁的readline
> -DWITH_EMBEDDED_SERVER=1 \                #是否要建立嵌入式伺服器
> -DWITH_DEBUG=0                            #禁用DEBUG(開啟影響效能)
# 提示:編譯時可配置的選項很多,具體可參考官方文件
[root@localhost mysql-5.5.22]# make && make install

下面設定不帶版本號的軟連結/usr/local/mysql,操作步驟如下:

[root@localhost mysql-5.5.22]# ln -s /usr/local/mysql-5.5.22 /usr/local/mysql
[root@localhost mysql-5.5.22]# ls /usr/local/mysql
bin      data  include         lib  mysql-test  scripts  sql-bench
COPYING  docs  INSTALL-BINARY  man  README      share    support-files

如果上述操作未出現錯誤,檢視/usr/local/mysql目錄下有內容,則MySQL5.5.22原始碼包採用cmake方式的安裝就算成功了。

5.2 建立MySQL多例項的資料檔案目錄

在企業中,通常以/data目錄作為MySQL多例項總的根目錄,然後規劃不同的數字(即MySQL例項埠號)作為/data下面的二級目錄,不同的二級目錄對應的數字就作為MySQL例項的埠號,以區別不同的例項,數字對應的二級目錄下包含MySQL的資料檔案,配置檔案及啟動檔案等。
下面以配置3306,3307兩個例項為例進行講解。建立MySQL多例項的目錄如下:

[root@localhost ~]# mkdir -p /data/{3306,3307}/data
[root@localhost ~]# tree /data/
/data/
├── 3306            #3306例項目錄
│ └── data        #3306例項的資料檔案目錄
├── 3307            #3307例項目錄
    └── data        #3307例項的資料檔案目錄


4 directories, 0 files

提示:
(1)mkdir -p /data/{3306,3307}/data相當於mkdir -p /data/3306/data;mkdir -p /data/3307/data兩條命令
(2)如果是建立多個目錄,可以增加如3308,3309這樣的目錄名,在生產環境中,一般為3~4個例項為佳。

5.3 建立MySQL多例項的配置檔案

MySQL資料庫預設為使用者提供了多個配置檔案模板,使用者可以根據伺服器硬體配置的大小來選擇。

[root@localhost mysql]# ls -l support-files/my*.cnf
-rw-r--r-- 1 root root  4751 719 21:33 support-files/my-huge.cnf
-rw-r--r-- 1 root root 19805 719 21:33 support-files/my-innodb-heavy-4G.cnf
-rw-r--r-- 1 root root  4725 719 21:33 support-files/my-large.cnf
-rw-r--r-- 1 root root  4736 719 21:33 support-files/my-medium.cnf
-rw-r--r-- 1 root root  2900 719 21:33 support-files/my-small.cnf

注意:
這些配置檔案裡的註釋非常詳細,不過是英文的。。。

上面是單例項的預設配置檔案模板,如果配置多例項,和單例項會有不同。為了讓MySQL多例項之間彼此獨立,要為每一個例項建立一個my.cnf配置檔案和一個啟動檔案MySQL,讓他們分別對應自己的資料檔案目錄data。
首先,通過vim命令新增配置檔案內容,命令如下:

vim /data/3306/my.cnf
vim /data/3307/my.cnf

不同的例項需要新增的my.cnf內容會有區別,其中的配置由官方的配置模板修改而來。當然,在實際工作中,我們是拿早已配置好的模板來進行修改的,可以通過rz等方式上傳配置檔案模板my.cnf檔案到相關目錄下。

MySQL3306,3307例項配置檔案如下

##例項3306配置檔案my.cnf
[root@localhost ~]# cat /data/3306/my.cnf
[client]
port		= 3306
socket		= /data/3306/mysql.sock
[mysqld]
user		= mysql
port		= 3306
socket		= /data/3306/mysql.sock
basedir		= /usr/local/mysql
datadir		= /data/3306/data
open_files_limit	= 1024
back_log = 600
max_connections = 800
max_connect_errors = 3000
table_open_cache = 614
external-locking = FALSE
max_allowed_packet = 8M
#binlog_cache_size = 1M
#max_heap_table_size = 64M
#read_buffer_size = 2M
#read_rnd_buffer_size = 16M
sort_buffer_size = 1M
join_buffer_size = 1M
thread_cache_size = 100
thread_concurrency = 2
query_cache_size = 2M
query_cache_limit = 1M
query_cache_min_res_unit = 2k
#ft_min_word_len = 4
#default-storage-engine = MYISAM
thread_stack = 192K
transaction_isolation = READ-COMMITTED
tmp_table_size = 2M
max_heap_table_size = 2M
#log-bin=mysql-bin
#binlog_format=mixed
#slow_query_log
long_query_time = 1
pid-file = /data/3306/mysql.pid
relay-log = /data/3306/relay-bin
relay-log-info-file = /data/3306/relay-log.info
binlog_cache_size = 1M
max_binlog_cache_size = 1M
max_binlog_size = 2M
key_buffer_size = 16M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
bulk_insert_buffer_size = 1M
lower_case_table_names = 1
skip-name-resolve
slave-skip-errors = 1032,1062
replicate-ignore-db = mysql

server-id = 1

#key_buffer_size = 32M
#bulk_insert_buffer_size = 64M
#myisam_sort_buffer_size = 128M
#myisam_max_sort_file_size = 10G
#myisam_repair_threads = 1
#myisam_recover
innodb_additional_mem_pool_size = 4M
innodb_buffer_pool_size = 32M
innodb_data_file_path = ibdata1:128M:autoextend
innodb_file_io_threads = 4
#innodb_write_io_threads = 8
#innodb_read_io_threads = 8
innodb_thread_concurrency = 8
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 2M
innodb_log_file_size = 4M
innodb_log_files_in_group = 3
innodb_max_dirty_pages_pct = 90
innodb_lock_wait_timeout = 120
innodb_file_per_table = 0

[mysqldump]
quick
max_allowed_packet = 2M

[mysql]
no-auto-rehash

#[myisamchk]
#key_buffer_size = 512M
#sort_buffer_size = 512M
#read_buffer = 8M
#write_buffer = 8M
#[mysqlhotcopy]
#interactive-timeout

[mysqld_safe]
log-error = /data/3306/mysql_yunjisuan3306.err
pid-file = /data/3306/mysqld.pid

提示:例項3307的配置檔案只需要將3306配置檔案裡的所有3306數字替換成3307(server-id換個數字)即可。

最終完成後的多例項根/data目錄結果如下:

[root@localhost ~]# tree /data
/data
├── 3306
│ ├── data
│ └── my.cnf      #這個就是3306例項的配置檔案
└── 3307
    ├── data
    └── my.cnf      #這個就是3307例項的配置檔案

4 directories, 2 files

5.4 建立MySQL多例項的啟動檔案

MySQL多例項啟動檔案的建立和配置檔案的建立幾乎一樣,也可以通過vim命令來新增,如下:

vim /data/3306/mysql
vim /data/3307/mysql

需要新增的MySQL啟動檔案內容如下。(當然,在實際工作中我們是拿早已配置好的模板來進行修改的,可以通過rz等方式上傳配置檔案模板MySQL檔案到相關目錄下)

[root@localhost ~]# cat /data/3306/mysql
#!/bin/bash
###############################################
#this scripts is created by Mr.chen at 2016-06-25

port=3306
mysql_user="root"
mysql_pwd=""            #這裡需要修改為使用者的實際密碼

CmdPath="/usr/local/mysql/bin"
mysql_sock="/data/${port}/mysql.sock"

#startup function
function_start_mysql(){
	
	if [ ! -e "$mysql_sock" ];then
		printf "Starting MySQL....\n"
		/bin/sh ${CmdPath}/mysqld_safe --defaults-file=/data/${port}/my.cnf 2>&1 >/dev/null &
	else
		printf "MySQL is running...\n"
		exit
	fi
}

#stop function
function_stop_mysql(){

	if [ ! -e "$mysql_sock" ];then
		printf "MySQL is stopped...\n"
		exit
	else
		printf "Stoping MySQL...\n"
		${CmdPath}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S /data/${port}/mysql.sock shutdown
	fi
}

#restart function
function_restart_mysql(){

	printf "Restarting MySQL...\n"
	function_stop_mysql
	sleep 2
	function_start_mysql
}

case $1 in 
start)
	function_start_mysql
;;
stop)
	function_stop_mysql
;;
restart)
	function_restart_mysql
;;
*)
	printf "Usage: /data/${port}/mysql{start|stop|restart}\n"
esac

3307例項的啟動檔案只需修改3306啟動檔案的埠即可

最終完成後的多例項根/data目錄結果如下:

[root@localhost ~]# tree /data
/data
├── 3306
├── data
├── my.cnf          #3306例項的配置檔案
└── mysql           #3306例項的啟動檔案
└── 3307
    ├── data
    ├── my.cnf          #3307例項的配置檔案
    └── mysql           #3307例項的啟動檔案

4 directories, 4 files

需要特別說明一下,在多例項啟動檔案中,啟動MySQL不同例項服務,所執行的命令實質是有區別的,例如,啟動3306例項的命令如下:
mysqld_safe --defaults-file=/data/3306/my.cnf 2>&1 >/dev/null &
啟動3307例項的命令如下:
mysqld_safe --defaults-file=/data/3307/my.cnf 2>&1 >/dev/null &
下面看看在多例項啟動檔案中,停止MySQL不同例項服務的實質命令。
停止3306例項的命令如下:
mysqladmin -uroot -pyunjisuan123 -S /data/3306/mysql.sock shutdown
停止3307例項的命令如下:
mysqladmin -u root -pyunjisuan123 -S /data/3307/mysql.sock shutdown

5.5 配置MySQL多例項的檔案許可權

1)通過下面的命令,授權mysql使用者和組管理整個多例項的根目錄/data

[root@localhost ~]# chown -R mysql.mysql /data
[root@localhost ~]# find /data -name "mysql" | xargs ls -l
-rw-r--r--. 1 mysql mysql 1039 Jul 20 19:33 /data/3306/mysql
-rw-r--r--. 1 mysql mysql 1039 Jul 20 19:34 /data/3307/mysql

2)通過下面的命令,授權MySQL多例項所有啟動檔案的mysql可執行,設定700許可權最佳,注意不要用755許可權,因為啟動檔案裡有資料庫管理員密碼,會被讀取到。

[root@localhost ~]# find /data -name "mysql" | xargs chmod 700
[root@localhost ~]# find /data -name "mysql" | xargs ls -l
-rwx------. 1 mysql mysql 1039 Jul 20 19:33 /data/3306/mysql
-rwx------. 1 mysql mysql 1039 Jul 20 19:34 /data/3307/mysql

5.6 MySQL相關命令加入全域性路徑的配置

(1)配置全域性路徑的意義

如果不為MySQL的命令配置全域性路徑,就無法直接在命令列輸入mysql這樣的命令,只能用全路徑命令(/usr/local/mysql/bin/mysql),這種帶著路徑輸入命令的方式很麻煩。

(2)配置MySQL全域性路徑的方法

1)確認mysql命令所在路徑,命令如下:

[root@localhost ~]# ls /usr/local/mysql/bin/mysql
/usr/local/mysql/bin/mysql

2)在PATH變數前面增加/usr/local/mysql/bin路徑,並追加到/etc/profile檔案中,命令如下:

[root@localhost ~]# echo 'export PATH=/usr/local/mysql/bin:$PATH' >> /etc/profile
#注意,echo後邊是單引號,雙引號的話變數內容會被解析掉。
[root@localhost ~]# tail -1 /etc/profile
export PATH=/usr/local/mysql/bin:$PATH
[root@localhost ~]# source /etc/profile
#執行source使上一行新增到/etc/profile中,內容直接生效
#以上命令的用途為定義mysql全域性路徑,實現在任意路徑執行mysql命令

提示:
更簡單的設定方法為用下面命令做軟連結:ln -s /usr/local/mysql/bin/* /usr/local/sbin/,把mysql命令說在路徑連結到全域性路徑/usr/local/sbin/的下面。

5.7 初始化MySQL多例項的資料庫檔案

上述步驟全都配置完畢後,就可以初始化資料庫檔案了,這個步驟其實也可以在編譯安裝MySQL之後就操作,只不過放到這裡更合理一些。

(1)初始化MySQL資料庫
初始化命令如下:

[root@localhost scripts]# ./mysql_install_db --basedir=/usr/local/mysql --datadir=/data/3306/data --user=mysql
[root@localhost scripts]# ./mysql_install_db --basedir=/usr/local/mysql --datadir=/data/3307/data --user=mysql

提示:
--basedir=/usr/local/mysql為MySQL的安裝路徑,--datadir為不同的例項資料目錄

(2)初始化資料庫的原理及結果說明

初始化資料庫的實質就是建立基礎的資料庫系統的庫檔案,例如:生成MySQL庫表等。
初始化資料庫後檢視對應例項的資料目錄,可以看到多瞭如下檔案:

[root@localhost scripts]# tree /data

#以下省略若干...

5.8 啟動MySQL多例項的命令

[root@localhost scripts]# /data/3306/mysql start
Starting MySQL....
[root@localhost scripts]# /data/3307/mysql start
Starting MySQL....
root@localhost scripts]# netstat -antup | grep 330
tcp        0      0 0.0.0.0:3307                0.0.0.0:*                   LISTEN      24743/mysqld        
tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      24020/mysqld   

從輸出中可以看到,3306和3307例項均已正常啟動。

六,配置及管理MySQL多例項資料庫

6.1 配置MySQL多例項資料庫開機自啟動

服務的開機自啟動很關鍵,MySQL多例項的啟動也不例外,把MySQL多例項的啟動命令加入/etc/rc.local,實現開機自啟動,命令如下:

[root@localhost ~]# echo "#mysql multi instances" >> /etc/rc.local 
[root@localhost ~]# echo "/data/3306/mysql start" >> /etc/rc.local
[root@localhost ~]# echo "/data/3307/mysql start" >> /etc/rc.local 
[root@localhost ~]# tail -3 /etc/rc.local 
#mysql multi instances
/data/3306/mysql start
/data/3307/mysql start

#這裡一定要確保MySQL指令碼可執行~

6.2 登陸MySQL測試

[root@localhost ~]# mysql -S /data/3306/mysql.sock  #直接敲就進來了,而且身份還是root。但是多了-S /data/3306/mysql.sock,用於區別登陸不同的例項
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.22 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;              #檢視當前所有的資料庫
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)
mysql> select user();               #檢視當前的登陸使用者
+----------------+
| user()         |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)

6.3 MySQL多例項資料庫的管理方法

  • MySQL安裝完成後,預設情況下,MySQl管理員的賬號root是無密碼的。登陸不同的例項需要指定不同例項的mysql.sock檔案路徑,這個mysql.sock是在my.cnf配置檔案裡指定的。

  • 下面是無密碼情況下登陸資料庫的方法,關鍵點是-S引數及後面指定的/data/33306/mysql.sock,注意,不同例項的sock雖然名字相同,但是路徑是不同的,因此是不同的檔案。

mysql -S /data/3306/mysql.sock
mysql -S /sata/3307/mysql.sock

下面是重啟對應例項資料庫的命令

/data/3306/mysql stop
/data/3307/mysql start

6.4 MySQL安全配置

MySQL管理員的賬號root密碼預設為空,極不安全,可以通過mysqladmin命令為MySQL不同例項的資料庫設定獨立的密碼,命令如下:

[root@localhost ~]# mysqladmin -u root -S /data/3306/mysql.sock password '123123'     #為mysql設定密碼
[root@localhost ~]# mysql -uroot -p -S /data/3306/mysql.sock       #無法直接登陸了
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.22 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 

#提示:3307例項設定方法和3306例項相同,只是連線時的mysql,sock路徑不同,這已經提醒多次,大家要注意

帶密碼登陸不同例項資料庫的方法:

#登陸3306例項的命令如下:
mysql -uroot -p123123 -S /data/3306/mysql.sock
#登陸3307例項的命令如下:
mysql -uroot -p123123 -S /data/3307/mysql.sock

提示:
基礎弱的同學,在測試時儘量保證多例項的密碼相同,可以減少麻煩,後面還原資料庫時會覆蓋密碼!
若要重啟多例項資料庫,也需要進行相應的如下配置。再重啟資料庫前,需要調整不同例項啟動檔案裡對應的資料庫密碼。

[root@localhost ~]# vim /data/3306/mysql
[root@localhost ~]# sed -n '7p' /data/3306/mysql  #這是之前mysql多例項啟動腳本里mysql的登陸密碼變數
mysql_pwd=""
[root@localhost ~]# sed -i '7 s#""#"123123"#' /data/3306/mysql
[root@localhost ~]# sed -n '7p' /data/3306/mysql
mysql_pwd="123123"          #修改成實際的登入密碼
[root@localhost ~]# sed -n '7p' /data/3307/mysql
mysql_pwd=""
[root@localhost ~]# sed -i '7 s#""#"123123"#' /data/3307/mysql
[root@localhost ~]# sed -n '7p' /data/3307/mysql
mysql_pwd="123123"

多例項下正常停止資料庫的命令如下:

/data/3306/mysql stop

由於選擇了mysqladmin shutdown的停止方式,所以停止資料庫時需要在啟動檔案裡配置資料庫的密碼

/data/3306/mysql start

重點提示:
禁止使用pkill,kill -9,killall -9等命令強制殺死資料庫,這會引起資料庫無法啟動等故障的發生。

6.5 如何再增加一個MySQL的例項

若再3306和3307例項的基礎上,再增加一個MySQL例項,該怎麼辦?下面給出增加一個MySQL3308埠例項的命令集合:

mkdir -p /data/3308/data
\cp /data/3306/my.cnf /data/3308/
\cp /data/3306/mysql /data/3308/
sed -i 's#3306#3308#g' /data/3308/my.cnf
sed -i 's#server-id = 1#server-id = 8#g' /data/3308/my.cnf
sed -i 's#3306#3308#g' /data/3308/mysql
chown -R mysql:mysql /data/3308
chmod 700 /data/3308/mysql
cd /usr/local/mysql/scripts
./mysql_install_db --datadir=/data/3308/data --basedir=/usr/local/mysql --user=mysql
chown -R mysql:mysql /data/3308
egrep "server-id|log-bin" /data/3308/my.cnf
/data/3308/mysql start

netstat -antup | grep 3308
#提示:最好把server-id按照IP地址最後一個小數點的數字設定
#成功標誌:多了一個啟動的埠3308

如果配置以後,服務啟動後卻沒有執行起來,別忘了一定要看MySQL錯誤日誌,在/data/3308/my.cnf最下面有錯誤日誌路徑地址。

6.6 多例項MySQL登陸問題分析

(1)多例項本地登入MySQL

多例項本地登入一般通過socket檔案來指定具體登陸到哪個例項,此檔案的具體位置是在MySQL編譯過程或my.cnf檔案中指定的。在本地登陸資料庫時,登陸程式會通過socket檔案來判斷登陸的是哪個資料庫例項。
例如:通過mysql -uroot -p '123123' -S /data/3307/mysql.sock可知,登陸的是3307這個例項。
mysql.sock檔案是MySQL伺服器端與本地MySQL客戶端進行通訊的UNIX套接字檔案。

(2)遠端連線登陸MySQL多例項

遠端登陸MySQL多例項中的一個例項時,通過TCP埠(port)來指定說要登陸的MySQL例項,此埠的配置是在MySQL配置檔案my.cnf中指定的。
例如:在mysql -uyunjisuan -p '123123' -h 192.168.200.101 -P 3307中,-P為埠引數,後面接具體的例項埠,埠是一種“邏輯連線位置”,是客戶端程式被分派到計算機上特殊服務程式的一種方式,強調提前在192.168.200.101上對yunjisuan使用者做了授權。

七, MySQL主從複製介紹

MySQL資料庫的主從複製方案,與使用scp/rsync等命令進行的檔案級別複製類似,都是資料的遠端傳輸,只不過MySQL的主從複製是其自帶的功能,無需藉助第三方工具,而且,MySQL的主從複製並不是資料庫磁碟上的檔案直接拷貝,而是通過邏輯的binlog日誌複製到要同步的伺服器本地,然後由本地的執行緒讀取日誌裡面的SQL語句,重新應用到MySQL資料庫中。

7.1 概述

  • MySQL資料庫支援單向,雙向,鏈式級聯,環狀等不同業務場景的複製。在複製過程中,一臺伺服器充當主伺服器(Master),接收來自使用者的內容更新,而一個或多個其他的伺服器充當從伺服器(Slave),接收來自主伺服器binlog檔案的日誌內容,解析出SQL,重新更新到從伺服器,使得主從伺服器資料達到一致。
  • 如果設定了鏈式級聯複製,那麼,從伺服器(Slave)本身除了充當從伺服器外,也會同時充當其下面從伺服器的主伺服器。鏈式級聯複製類似A-->B-->C的複製形式。

下圖為單向主從複製架構邏輯圖,此架構只能在Master端進行資料寫入

下圖為雙向主主複製邏輯架構圖,此架構可以在Master1端或Master2端進行資料寫入,或者兩端同時寫入資料(需要特殊設定)

下圖為線性級聯單向雙主複製邏輯架構圖,此架構只能在Master1端進行資料寫入,工作場景中,Master1和master2作為主主互備,Slave1作為從庫,中間的Master2需要做特殊的設定。

下圖為環狀級聯單向多主同步邏輯架構圖,任意一個點都可以寫入資料,此架構比較複雜,屬於極端環境下的“成品”,一般場景慎用

在當前的生產工作中,MySQL主從複製都是非同步的複製方式,既不是嚴格實時的資料同步,但是正常情況下給使用者的體驗是真實的。

7.2 MySQL主從複製的企業應用場景

MySQL主從複製叢集功能使得MySQL資料庫支援大規模高併發讀寫成為可能,同時有效地保護了物理伺服器宕機場景的資料備份。

應用場景1:從伺服器作為主伺服器的實時資料備份

  • 主從伺服器架構的設定可以大大加強MySQL資料庫架構的健壯性。例如:當主伺服器出現問題時,我們可以人工或設定自動切換到從伺服器繼續提供服務,此時從伺服器的資料與宕機時的主資料庫幾乎是一致的。
  • 這類似NFS儲存資料通過inotify + rsync同步到備份的NFS伺服器,只不過MySQL的複製方案是其自帶的工具。
  • 利用MySQL的複製功能進行資料備份時,在硬體故障,軟體故障的場景下,該資料備份是有效的,但對於人為地執行drop,delete等語句刪除資料的情況,從庫的備份功能就沒用了,因為從伺服器也會執行刪除的語句。

應用場景2:主從伺服器實現讀寫分離,從伺服器實現負載均衡

  • 主從伺服器架構可通過程式(PHP,java等)或代理軟體(mysql-proxy,Amoeba)實現對使用者(客戶端)的請求讀寫分離,即讓從伺服器僅僅處理使用者的select查詢請求,降低使用者查詢響應時間,以及同時讀寫在主伺服器上帶來的訪問壓力。對於更新的資料(例如:update,insert,delete語句),則仍然交給主伺服器處理,確保主伺服器和從伺服器保持實時同步。
  • 百度,淘寶,新浪等絕大多數的網站都是使用者瀏覽頁面多於使用者釋出內容,因此通過在從伺服器上接收只讀請求,就可以很好地減輕主庫的讀壓力,且從伺服器可以很容易地擴充套件為多臺,使用LVS做負載均衡效果就非常棒了,這就是傳說中的資料庫讀寫分離架構。邏輯架構圖如下所示:

應用場景3:把多個從伺服器根據業務重要性進行拆分訪問

可以把幾個不同的從伺服器,根據公司的業務進行拆分。例如:有為外部使用者提供查詢服務的從伺服器,有內部DBA用來資料備份的從伺服器,還有為公司內部人員提供訪問的後臺,指令碼,日誌分析及供開發人員查詢使用的從伺服器。這樣的拆分除了減輕主伺服器的壓力外,還可以使資料庫對外部使用者瀏覽,內部使用者業務處理及DBA人員的備份等互不影響。

7.3 實現MySQL主從讀寫分離的方案

(1)通過程式實現讀寫分離(效能和效率最佳,推薦)

PHP和Java程式都可以通過設定多個連線檔案輕鬆地實現對資料庫的讀寫分離,即當語句關鍵字為select時,就去連線讀庫的連線檔案,若為update,insert,delete時,則連線寫庫的連線檔案。
通過程式實現讀寫分離的缺點就是需要開發人員對程式進行改造,使其對下層不透明,但這種方式更容易開發和實現,適合網際網路業務場景。

根據業務重要性拆分從庫方案

(2)通過開源的軟體實現讀寫分離

MySQL-proxy,Amoeba等代理軟體也可以實現讀寫分離功能,這些軟體的穩定性和功能一般,不建議生產使用。絕大多數公司常用的還是在應用端發程式實現讀寫分離。

(3)大型門戶獨立開發DAL層綜合軟體

百度,阿里等大型門戶都有開發牛人,會花大力氣開發適合自己業務的讀寫分離,負載均衡,監控報警,自動擴容,自動收縮等一系列功能的DAL層軟體。

7.4 MySQL主從複製原理介紹

  • MySQL的主從複製是一個非同步的複製過程(雖然一般情況下感覺是實時的),資料將從一個MySQL資料庫(我們稱之為Master)複製到另一個MySQL資料庫(我們稱之為Slave),在Master與Slave之間實現整個主從複製的過程是由三個執行緒參與完成的。其中有兩個執行緒(SQL執行緒和I/O執行緒)在Slave端,另外一個執行緒(I/O執行緒)在Master端。
  • 要實現MySQL的主從複製,首先必須開啟Master端的binlog記錄功能,否則就無法實現。因為整個複製過程實際上就是Slave從Master端獲取binlog日誌,然後再在Slave上以相同順序執行獲取的binlog日誌中所記錄的各種SQL操作。
  • 要開啟MySQL的binlog記錄功能,可通過在MySQL的配置檔案my.cnf中的mysqld模組([mysqld]標識後的引數部分)增加“log-bin”引數選項來實現,具體資訊如下。
[mysqld]
log-bin=/data/3306/mysql-bin

提示:
有些同學把log-bin放在了配置檔案結尾,而不是[mysqld]標識後,從而導致配置複製不成功。

7.5 MySQL主從複製原理過程詳細描述

下面簡單描述MySQL Replication的複製原理過程

1)在Slave伺服器上執行start slave命令開啟主從複製開關,開始進行主從複製
2)此時,Slave伺服器的I/O執行緒會通過在Master上已經授權的複製使用者許可權請求連線Master伺服器,並請求從指定binlog日誌檔案的指定位置(日誌檔名和位置就是在配置主從複製服務時執行change master命令指定的)之後開始傳送binlog日誌內容。
3)Master伺服器接收到來自Slave伺服器的I/O執行緒的請求後,其上負責複製的I/O執行緒會根據Slave伺服器的I/O執行緒請求的資訊分批讀取指定binlog日誌檔案指定位置之後的binlog日誌資訊,然後返回給Slave端的I/O執行緒。返回的資訊中除了binlog日誌內容外,還有在Master伺服器端記錄的新的binlog檔名稱,以及在新的binlog中的下一個指定更新位置。
4)當Slave伺服器的I/O執行緒獲取到Master伺服器上I/O執行緒傳送的日誌內容,日誌檔案及位置點後,會將binlog日誌內容依次寫到Slave端自身的Relay Log(即中繼日誌)檔案(MySQL-relay-bin.xxxx)的最末端,並將新的binlog檔名和位置記錄到master-info檔案中,以便下一次讀取Master端新binlog日誌時能夠告訴Master伺服器從新binlog日誌的指定檔案及位置開始請求新的binlog日誌內容。
5)Slave伺服器端的SQL執行緒會實時檢測本地Relay Log中I/O執行緒新增加的日誌內容,然後及時地把Relay Log檔案中的內容解析成SQL語句,並在自身Slave伺服器上按解析SQL語句的位置順序執行應用這些SQL語句,並在relay-log.info中記錄當前應用中繼日誌的檔名及位置點。

經過了上面的過程,就可以確保在Master端和Slave端執行了同樣的SQL語句。當複製狀態正常時,Master端和Slave端的資料是完全一樣的。當然,MySQL的複製機制也有一些特殊情況,具體請參考官方的說明,大多數情況下,同學們不用擔心。

MySQL Replication的複製原理邏輯圖

特別說明:
當企業面試MySQL主從複製原理時,不管是面試還是筆試,都要儘量畫圖表達,而不是口頭講或文字描述,面試時可以找黑板或拿出紙來給面試官詳細講解。

下面針對MySQL主從複製原理的重點進行小結:

  • 主從複製是非同步的邏輯的SQL語句級的複製
  • 複製時,主庫有一個I/O執行緒,從庫有兩個執行緒,即I/O和SQL執行緒
  • 實現主從複製的必要條件是主庫要開啟記錄binlog功能
  • 作為複製的所有MySQL節點的server-id都不能相同。
  • binlog檔案只記錄對資料庫有更改的SQL語句(來自主資料庫內容的變更),不記錄任何查詢(如select,show)語句。

八,MySQL主從複製實踐

8.1 主從複製實踐準備

8.1.1 主從複製資料庫實戰環境準備

MySQL主從複製實踐對環境的要求比較簡單,可以是單機單資料庫多例項的環境,也可以是兩臺伺服器,每個機器一個獨立資料庫的環境。本文以單機資料庫多例項的環境為例講解。例項埠資訊檢視如下:

[root@localhost ~]# ss -antup | grep 330
tcp    LISTEN     0      128                    *:3307                  *:*      users:(("mysqld",3910,11))
tcp    LISTEN     0      128                    *:3306                  *:*      users:(("mysqld",2450,11))

提示:
這裡把3306例項作為主庫,3307例項作為從庫,如果根據前面的內容配置了MySQL多例項環境,直接開啟多例項環境使用即可。

8.1.2 定義主從複製需要的伺服器角色

這裡的主從複製技術是針對前面的內容以單機資料庫多例項環境來講的。一般情況下,小企業在做常規的主從複製時,主從伺服器多數在不同的機器上,並且監聽的埠均為預設的3306.雖然不在同一個機器上,但是步驟和過程卻是一樣的。
同學們在掌握了但資料庫多例項的同步方法後,可以自己適當擴充套件,完成異機相同埠之間的主從複製。

8.1.3 資料庫中英文名稱約定

8.2 在主庫Master上執行操作配置

8.2.1 設定server-id值並開啟binlog功能引數

根據之前介紹的MySQL主從複製原理我們知道,要實現主從複製,關鍵是要開啟binlog日誌功能,所以,首先來開啟主庫的binlog日誌引數。

1)修改主庫的配置檔案。執行vi /data/3306/my.cnf,編輯多例項3006的my.cnf配置檔案,按如下內容修改兩個引數:

[mysqld]
server-id = 1               #用於同步的每臺機器或例項server-id都不能相同
log-bin = /data/3306/mysql-bin     #binlog日誌的位置 

提示:

上面的兩個引數要放在my.cnf中的[mysqld]模組下,否則會出錯。
不同例項間server-id的值不可以重複
要先在my.cnf配置檔案中查詢相關引數,並按要求修改。若發現不存在,再新增引數,切記,引數不能重複。
修改my.cnf配置後,需要重啟動資料庫,命令為:/data/3306/mysql restart ,注意要確認真正重啟了。

2)檢查配置引數後的結果,如下:

root@localhost ~]# egrep "server-id|log-bin" /data/3306/my.cnf
server-id = 1
log-bin=/data/3306/mysql-bin        #log-bin後面也可以不帶等號內容,MySQL會使用預設日誌

3)重啟主庫MySQL服務,命令如下:

[root@localhost ~]# /data/3306/mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL....

4)登陸資料庫,檢查引數的更改情況,如下:

[root@localhost ~]# mysql -uroot -p123123 -S /data/3306/mysql.sock       #登陸3306例項
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.22-log Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'server_id';         #檢視MySQL的系統變數(like類似於grep過濾)
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 1     |           #配置的server_id為1
+---------------+-------+
1 row in set (0.00 sec)

mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |           #binlog功能已開啟
+---------------+-------+
1 row in set (0.00 sec)

mysql> 

#這樣,binlog功能就開啟了。

8.2.2 在主庫上建立用於主從複製的賬號

根據主從複製的原理,從庫要想和主庫同步,必須有一個可以連線主庫的賬號,並且這個賬號是主庫上建立的,許可權是允許主庫的從庫連線並同步資料。

1)登陸MySQL3306例項主資料庫,命令如下:

[root@localhost ~]# mysql -uroot -p123123 -S /data/3306/mysql.sock

2)建立用於從庫複製的賬號yunjisuan,命令如下:

mysql> grant replication slave on *.* to 'yunjisuan'@'192.168.0.%' identified by 'yunjisuan123';
Query OK, 0 rows affected (0.00 sec)

#語句說明:
1)replication slave為mysql同步的必須許可權,此處不要授權all許可權
2)*.* 表示所有庫所有表,也可以指定具體的庫和表進行復制。例如yunjisuan.test中,yunjisuan為庫名,test為表名
3)'yunjisuan'@'192.168.0.%' yunjisuan為同步賬號。192.168.0.%為授權主機網段,使用了%表示允許整個192.168.0.0網段可以用yunjisuan這個使用者訪問資料庫
4)identified by 'yunjisuan123';  yunjisuan123為密碼,實際環境下設定的複雜些為好

建立完賬號並授權後,需要重新整理許可權,使授權的許可權生效

mysql> flush privileges;            #重新整理許可權
Query OK, 0 rows affected (0.00 sec)

3)檢查主庫建立的yunjisuan複製賬號命令及結果如下:

mysql> select user,host from mysql.user;
+-----------+-------------+
| user      | host        |
+-----------+-------------+
| root      | 127.0.0.1   |
| yunjisuan | 192.168.0.% |         #出現這行表示複製賬號已經配置好了
| root      | ::1         |
|           | localhost   |
| root      | localhost   |
+-----------+-------------+
5 rows in set (0.00 sec)

#說明:
MySQL裡的授權使用者是以資料表格的形式儲存在mysql這個庫的user表裡。

mysql> select user,host from mysql.user where user='yunjisuan';  #where是SQL查詢語句的條件
+-----------+-------------+
| user      | host        |
+-----------+-------------+
| yunjisuan | 192.168.0.% |
+-----------+-------------+
1 row in set (0.00 sec)

mysql> show grants for yunjisuan@'192.168.0.%';         #檢視賬號的授權情況
+--------------------------------------------------------------------------------------------------------------------------------+
| Grants for yunjisuan@192.168.0.%                                                                                               |
+--------------------------------------------------------------------------------------------------------------------------------+
| GRANT REPLICATION SLAVE ON *.* TO 'yunjisuan'@'192.168.0.%' IDENTIFIED BY PASSWORD '*A2CC7FA422EF5A7CB098FEA7732C1F78CDC32F67' |               #結果顯示授權正確
+--------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

8.2.3 實現對主資料庫鎖表只讀

1)對主資料庫鎖表只讀(當前視窗不要關掉)的命令如下:

mysql> flush table with read lock;
Query OK, 0 rows affected (0.00 sec)

提示:
在引擎不同的情況下,這個鎖表命令的時間會受下面引數的控制。鎖表時,如果超過設定時間不操作會自動解鎖。
預設情況下自動解鎖的時長引數值如下:

mysql> show variables like '%timeout%';
+----------------------------+----------+
| Variable_name              | Value    |
+----------------------------+----------+
| connect_timeout            | 10       |
| delayed_insert_timeout     | 300      |
| innodb_lock_wait_timeout   | 120      |
| innodb_rollback_on_timeout | OFF      |
| interactive_timeout        | 28800    |       #自動解鎖時間受本引數影響
| lock_wait_timeout          | 31536000 |
| net_read_timeout           | 30       |
| net_write_timeout          | 60       |
| slave_net_timeout          | 3600     |
| wait_timeout               | 28800    |       #自動解鎖時間受本引數影響
+----------------------------+----------+
10 rows in set (0.00 sec)

#提示:有關這兩個引數,請同學們自行測試

2)鎖表後檢視主庫狀態。可通過當前binlog日誌檔名和二進位制binlog日誌偏移量來檢視,結果如下:

注意,show master status;命令顯示的資訊要記錄在案,後面的從庫匯入全備後,繼續和主庫複製時就是要從這個位置開始。

mysql> show master status;
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      345 |              |                  |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

或者新開一個命令列視窗,用如下命令檢視鎖表後的主庫binlog位置點資訊:

[root@localhost ~]# mysql -uroot -p123123 -S /data/3306/mysql.sock -e "show master status"
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      533 |              |                  |
+------------------+----------+--------------+------------------+

3)鎖表後,一定要單開一個新的SSH視窗,匯出資料庫的所有資料,如果資料量很大(50GB以上),並且允許停機,可以停庫直接打包資料檔案進行遷移,那樣更快。

[root@localhost ~]# mkdir -p /server/backup
[root@localhost ~]# mysqldump -uroot -p123123 -S /data/3306/mysql.sock --events -A -B | gzip >/server/backup/mysql_bak.$(date +%F).sql.gz

#注意:-A表示備份所有庫;-B表示增加use DB和 drop 等(導庫時會直接覆蓋原有的)

[root@localhost ~]# ll /server/backup/mysql_bak.2017-07-21.sql.gz 
-rw-r--r--. 1 root root 137344 Jul 21 10:17 /server/backup/mysql_bak.2017-07-21.sql.gz

#為了確保匯出資料期間,資料庫沒有資料插入,導庫完畢可以再次檢查主庫狀態資訊,結果如下:

[root@localhost ~]# mysql -uroot -p123123 -S /data/3306/mysql.sock -e "show master status"
+------------------+----------+--------------+------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000001 |      533 |              |                  |
+------------------+----------+--------------+------------------+

提示:若無特殊情況,binlog檔案及位置點和鎖表後匯出資料前是一致的,即沒有變化。
#匯出資料完畢後,解鎖主庫,恢復可寫,命令如下.因為主庫還要對外提供服務,不能一直鎖定不讓使用者訪問。

mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)

#可能會有同學因為鎖表後的binlog位置問題犯迷糊,實際上做從庫前,無論主庫更新了多少資料,最後從庫都可以從上面show master status的位置很快趕上主庫的進度。

8.2.4 把主庫匯出的MySQL資料遷移到從庫

下面主要講解單資料庫多例項的主從配置,也就是說,mysqldump備份的3306例項的資料和要恢復的3307例項在一臺機器上,因此無需異地複製拷貝。想檢視主庫匯出的資料,如下:

[root@localhost ~]# ll /server/backup/mysql_bak.2017-07-21.sql.gz 
-rw-r--r--. 1 root root 137344 Jul 21 10:17 /server/backup/mysql_bak.2017-07-21.sql.gz

8.3 在MySQL從庫上執行的操作過程

8.3.1 設定server-id值並關閉binlog功能引數

  • 資料庫的server-id一般在一套主從複製體系內是唯一的,這裡從庫的server-id要和主庫及其他從庫的不同,並且要註釋掉從庫的binlog引數配置,如果從庫不做級聯複製,並且不作為備份用,就不要開啟binlog,開啟了反而會增加從庫磁碟I/O等的壓力。
  • 但是,有以下兩種情況需要開啟從庫的binlog記錄功能,記錄資料庫更新的SQL語句:
  • 級聯同步A-->B-->C中間的B時,就要開啟binlog記錄功能。
  • 在從庫做資料庫備份,資料庫備份必須要有全備和binlog日誌,才是完整的備份。

(1)修改配置檔案,配置從庫1的相關引數

執行vi /data/3307/my.cnf,編輯my.cnf配置檔案,按如下內容修改兩個引數:

[mysqld]
server-id = 3       #調整等號後的數值,和任何一個數據庫例項都不同

提示:
上面兩引數要放在my.cnf中的[mysqld]模組下,否則會出錯。
server-id的值不能和任何MySQL例項重複。
要先在檔案中查詢相關引數按要求修改。若發現不存在,再新增引數,切記,引數不能重複。
修改my.cnf配置後需要重啟資料庫,命令為:/data/3307/mysql restart,注意要確認真正重啟了。

(2)檢查配置引數後的結果
命令如下:

[root@localhost ~]# egrep "server-id|log-bin" /data/3307/my.cnf
server-id = 3

(3)重啟3307的從資料庫
命令如下:

[root@localhost ~]# /data/3307/mysql restart
Restarting MySQL...
Stoping MySQL...
Starting MySQL....
[root@localhost ~]# ss -antup | grep 3307
tcp    LISTEN     0      128                    *:3307                  *:*      users:(("mysqld",5659,11))

(4)登陸資料庫檢查引數的改變情況
命令如下:

[root@localhost ~]# mysql -uroot -p123123 -S /data/3307/mysql.sock 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.22 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'log_bin';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

mysql> show variables like 'server_id';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| server_id     | 3     |
+---------------+-------+
1 row in set (0.00 sec)

mysql> 

8.3.2 把從主庫mysqldump匯出的資料恢復到從庫

操作命令如下:

[root@localhost ~]# cd /server/backup/
[root@localhost backup]# ls -l
total 136
-rw-r--r--. 1 root root 137344 Jul 21 10:17 mysql_bak.2017-07-21.sql.gz
[root@localhost backup]# gzip -d mysql_bak.2017-07-21.sql.gz 
[root@localhost backup]# ll
total 496
-rw-r--r--. 1 root root 506730 Jul 21 10:17 mysql_bak.2017-07-21.sql
[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock <mysql_bak.2017-07-21.sql           #這是把資料還原到3307例項的命令

#提示:
如果備份時使用了-A引數,則在還原資料到3307例項時,登陸3307例項的密碼也會和3306主庫的一致,因為3307例項的授權表MySQL也被覆蓋了。

8.3.3 登陸3307從庫,配置複製引數

(1)MySQL從庫連線主庫的配置資訊如下:

CHANGE MASTER TO
MASTER_HOST='192.168.0.200',         #這裡是主庫的IP
MASTER_PORT=3306,                    #這裡是主庫的埠,從庫埠可以和主庫不同
MASTER_USER='yunjisuan',             #這裡是主庫上建立的用於複製的使用者yunjisuan
MASTER_PASSWORD='yunjisuan123',      #這裡是yunjisuan使用者的密碼
MASTER_LOG_FILE='mysql-bin.000001',  #這裡是show master status時檢視到的二進位制日誌檔名稱,注意不能多空格
MASTER_LOG_POS=533;                  #這裡是show master status時檢視到的二進位制日誌偏移量,注意不能多空格

#提示:字串用單引號括起來,數值不用引號,注意內容前後不能有空格。

(2)登陸資料庫後,去掉上述語句中的註釋,執行如下:

mysql> CHANGE MASTER TO MASTER_HOST='192.168.0.200',MASTER_PORT=3306,MASTER_USER='yunjisuan',MASTER_PASSWORD='yunjisuan123',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=533;

#提示:這個步驟的引數一定不能錯,否則,資料庫複製配置會失敗

上述操作的原理實際上是把使用者密碼等資訊寫入從庫新的master.info檔案中

[root@localhost backup]# ll /data/3307/data/master.info 
-rw-rw----. 1 mysql mysql 90 Jul 21 11:31 /data/3307/data/master.info
[root@localhost backup]# cat /data/3307/data/master.info
18
mysql-bin.000001                    #這裡是show master status時檢視的二進位制日誌檔名稱
533                                 #這裡是show master status時檢視的二進位制日誌偏移量
192.168.0.200                       #這裡是主庫的IP
yunjisuan                           #這裡是主庫上建立的用於複製的使用者yunjisuan
yunjisuan123                        #這裡是yunjisuan使用者的密碼
3306                                #這裡是主庫的埠
60

0...以下省略若干...

8.4 啟動從庫同步開關,測試主從複製配置情況

(1)啟動從庫主從複製開關,並檢視複製狀態
相關語句如下:

[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock -e "start slave"
[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock -e "show slave status\G"
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.200
                  Master_User: yunjisuan
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000001
          Read_Master_Log_Pos: 533
               Relay_Log_File: relay-bin.000002
                Relay_Log_Pos: 253
        Relay_Master_Log_File: mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB: 
          Replicate_Ignore_DB: mysql
           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: 533
              Relay_Log_Space: 403
              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: 0
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: 1

主從同步是否成功,最關鍵的為下面的3項狀態引數:

[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock -e "show slave status\G" | egrep "IO_Running|SQL_Running|Seconds_Behind_Master"
        Slave_IO_Running: Yes
        Slave_SQL_Running: Yes
        Seconds_Behind_Master: 0

  • [x] :Slave_IO_Running: Yes,這個時I/O執行緒狀態,I/O執行緒負責從從庫到主庫讀取binlog日誌,並寫入從庫的中繼日誌,狀態為Yes表示I/O執行緒工作正常。
  • [x] :Slave_SQL_Running: Yes,這個是SQL執行緒狀態,SQL執行緒負責讀取中繼日誌(relay-log)中的資料並轉換為SQL語句應用到從資料庫中,狀態為Yes表示I/O執行緒工作正常。
  • [x] :Seconds_Behind_Master:0,這個是複製過程中從庫比主庫延遲的秒數,這個引數極度重要,但企業裡更準確地判斷主從延遲的方法為:在主庫寫時間戳,然後從庫讀取時間戳,和當前資料庫時間進行比較,從而認定是否延遲。

(2)測試主從複製結果
在主庫上寫入資料,然後觀察從庫的資料狀況。

[root@localhost backup]# mysql -uroot -p123123 -S /data/3306/mysql.sock -e "create database benet"
[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock -e "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| benet              |
| mysql              |
| performance_schema |
| test               |
+--------------------+
[root@localhost backup]# mysql -uroot -p123123 -S /data/3306/mysql.sock -e "create database yunjisuan"
[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock -e "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| benet              |
| mysql              |
| performance_schema |
| test               |
| yunjisuan          |
+--------------------+
[root@localhost backup]# mysql -uroot -p123123 -S /data/3306/mysql.sock -e "drop database yunjisuan"
[root@localhost backup]# mysql -uroot -p123123 -S /data/3307/mysql.sock -e "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| benet              |
| mysql              |
| performance_schema |
| test               |
+--------------------+

#根據測試可以判斷,主從庫是同步的。

8.5 MySQL主從複製配置步驟小結

MySQL主從複製配置完整步驟如下:

  1. 準備兩臺資料庫環境或單臺多例項環境,確定能正常啟動和登陸
  2. 配置my.cnf檔案:主庫配置log-bin和server-id引數;從庫配置server-id,該值不能和主庫及其他從庫一樣,一般不開啟從庫log-bin功能。注意,配置引數後要重啟才能生效。
  3. 登陸主庫,增加從庫連線主庫同步的賬戶,例如:yunjisuan,並授權replication slave同步的許可權。
  4. 登陸主庫,整庫鎖表flush table with read lock(視窗關閉後即失效,超時引數設定的時間到了,鎖表也失效),然後show master status檢視binlog的位置狀態。
  5. 新開視窗,在Linux命令列備份匯出原有的資料庫資料,並拷貝到從庫所在的伺服器目錄。如果資料庫資料量很大,並且允許停機,可以停機打包,而不用mysqldump。
  6. 匯出主庫資料後,執行unlock tables解鎖主庫。
  7. 把主庫匯出的資料恢復到從庫
  8. 根據主庫的show master status檢視到的binlog的位置狀態,在從庫執行change master to....語句。
  9. 從庫開啟複製開關,即執行start slave;。
  10. 從庫show slave status\G,檢查同步狀態,並在主庫進行更新測試。

8.6 MySQL主從複製執行緒狀態說明及用途

8.6.1 MySQL主從複製主庫I/O執行緒狀態說明

(1)登陸主資料庫檢視MySQL執行緒的同步狀態

mysql> show processlist\G
*************************** 1. row ***************************
     Id: 1
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: NULL
   Info: show processlist
*************************** 2. row ***************************
     Id: 5
   User: yunjisuan
   Host: 192.168.0.200:42008
     db: NULL
Command: Binlog Dump
   Time: 267
  State: Master has sent all binlog to slave; waiting for binlog to be updated
   Info: NULL
2 rows in set (0.00 sec)

#提示:上述狀態的意思是執行緒已經從binlog日誌讀取所有更新,並已經發送到了從資料庫伺服器。執行緒目前為空閒狀態,等待由主伺服器上二進位制日誌中的新事件更新。

下圖中列出了主伺服器binlog Dump執行緒中State列的最常見狀態。如果你沒有在主伺服器上看見任何binlog Dump執行緒,則說明覆制沒有執行,二進位制binlog日誌由各種事件組成,事件通常會為更新新增資訊。

(2)登陸從資料庫檢視MySQL執行緒工作狀態
從庫有兩個執行緒,即I/O和SQL執行緒。從庫I/O執行緒的狀態如下:

mysql> show processlist\G
*************************** 1. row ***************************
     Id: 3
   User: root
   Host: localhost
     db: NULL
Command: Query
   Time: 0
  State: NULL
   Info: show processlist
*************************** 2. row ***************************
     Id: 8
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 659
  State: Waiting for master to send event
   Info: NULL
*************************** 3. row ***************************
     Id: 9
   User: system user
   Host: 
     db: NULL
Command: Connect
   Time: 511
  State: Slave has read all relay log; waiting for the slave I/O thread to update it
   Info: NULL
3 rows in set (0.00 sec)

下圖列出了從伺服器的I/O執行緒的State列的最常見的狀態。該狀態也出現在Slave_IO_State列,由SHOW SLAVE STATUS顯示。

下圖列出了從伺服器的SQL執行緒的State列的最常見狀態

8.6.2 檢視MySQL執行緒同步狀態的用途

  • 通過MySQL執行緒同步狀態可以看到同步是否正常進行,故障的位置是什麼,另外還可檢視資料庫同步是否完成,可用於主庫宕機切換資料庫或人工資料庫主從切換遷移等。
  • 例如:主庫宕機,要選擇最快的從庫將其提升為主庫,就需要檢視主從庫的執行緒狀態,如果主從複製在正常情況下進行角色切換,也需要檢視主從庫的執行緒狀態,根據複製狀態確定更新是否完成。

8.7 MySQL主從複製更多應用技巧實踐

8.7.1 工作中MySQL從庫停止複製故障案例

模擬重現故障的能力是運維人員最重要的能力。下面就來次模擬操作。先在從庫建立一個庫,然後去主庫建立同名的庫來模擬資料衝突,命令如下:

mysql> show slave status\G
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.0.200
                  Master_User: yunjisuan
                  Master_Port: 3306
                Connect_Retry: 60
              Master_Log_File: mysql-bin.000003
          Read_Master_Log_Pos: 544
               Relay_Log_File: relay-bin.000010
                Relay_Log_Pos: 336
        Relay_Master_Log_File: mysql-bin.000003
             Slave_IO_Running: Yes
            Slave_SQL_Running: No
              Replicate_Do_DB: 
          Replicate_Ignore_DB: mysql
           Replicate_Do_Table: 
       Replicate_Ignore_Table: 
      Replicate_Wild_Do_Table: 
  Replicate_Wild_Ignore_Table: 
                   Last_Errno: 1007
                   Last_Error: Error 'Can't create database 'yunjisuan'; database exists' on query. Default database: 'yunjisuan'. Query: 'create database yunjisuan'
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 451
              Relay_Log_Space: 810
              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: 1007
               Last_SQL_Error: Error 'Can't create database 'yunjisuan'; database exists' on query. Default database: 'yunjisuan'. Query: 'create database yunjisuan'
  Replicate_Ignore_Server_Ids: 
             Master_Server_Id: 1
1 row in set (0.00 sec)

對於該衝突,解決辦法如下

辦法一:關閉從同步,調動sql_slave指標

mysql> stop slave;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> set global sql_slave_skip_counter=1;   #將sql執行緒同步指標向下移動一個,如果多次不同步,可以重複操作
Query OK, 0 rows affected (0.00 sec)

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

對於普通的網際網路業務,上述的移動指標的操作帶來的問題不是很大。當然,要在確認不影響公司業務的前提下。
若是在企業場景下,對當前業務來說,解決主從同步比主從不一致更重要,如果主從資料一致也是很重要的,那就再找個時間恢復這個從庫。
是主從資料不一致更重要,還是保持主從同步持續狀態更重要,要根據業務選擇。這樣Slave就會與Master同步了,主要關鍵點如下:

            Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            Seconds_Behind_Master: 0   #0表示已經同步狀態

#提示:set global sql_slave_skip_counter=n;     #n取值>0,忽略執行N個更新。

辦法二:根據可以忽略的錯誤號事先在配置檔案中配置,跳過指定的不影響業務資料的錯誤,例如:

[root@localhost ~]# grep slave-skip /data/3306/my.cnf
slave-skip-errors = 1032,1062

#提示:類似由於入庫重複導致的失敗可以忽略,其他情況是不是可以忽略需要根據不同公司的具體業務來評估。

其他可能引起復制故障的原因:

  • MySQL自身的原因及人為重複插入資料。
  • 不同的資料庫版本會引起不同步,低版本到高版本可以,但是高版本不能往低版本同步。
  • MySQL的執行錯誤或程式bug
  • binlog記錄模式,例如:row level模式就比預設的語句模式要好。

8.7.2 讓MySQL從庫記錄binlog日誌的方法

從庫需要記錄binlog的應用場景:當前的從庫還要作為其他從庫的主庫,例如級聯複製或雙主互為主從場景的情況下。下面介紹從庫記錄binlog日誌的方法。
在從庫的my.cnf中加入如下引數,然後重啟服務生效即可。

    log-slave-updates       #必須要有這個引數
    log-bin = /data/3307/mysql-bin
    expire_logs_days = 7    #相當於find /data/3307/ -type f -name "mysql-bin.000*" -mtime +7 | xargs rm -f

8.7.3 MySQL主從複製叢集架構的資料備份策略

  • 有主從複製了,還需要做定時全量加增量備份麼?答案是肯定的!
    因為,如果主庫有語句級誤操作(例如:drop database yunjisuan;),從庫也會執行drop database yunjisuan;,這樣MySQL主從庫就都刪除了該資料。
  • 把從庫作為資料庫備份伺服器時,備份策略如下:
    高併發業務場景備份時,可以選擇在一臺從庫上備份(Slave5),把從庫作為資料庫備份伺服器時需要在從庫開啟binlog功能,其邏輯圖如下所示:

步驟如下:
1)選擇一個不對外提供服務的從庫,這樣可以確保和主庫更新最接近,專門用於做資料備份。
2)開啟從庫的binlog功能

備份時可以選擇只停止SQL執行緒,停止應用SQL語句到資料庫,I/O執行緒保留工作狀態,執行命令為stop slave sql_thread;,備份方式可以採取mysqldump邏輯備份或直接物理備份,例如:使用cp,tar(針對/data目錄)工具或xtrabackup(第三方的物理備份軟體)進行備份,則邏輯備份和物理備份的選擇,一般是根據總的備份資料量的多少進行選擇的,資料量低於30G,建議選擇mysqldump邏輯備份方法,安全穩定,最後把全備和binlog資料傳送到備份伺服器上留存。

8.7.4 MySQL主從複製延遲問題的原因及解決方案

問題一:主庫的從庫太多,導致複製延遲

從庫數量以3~5個為宜,要複製的從節點數量過多,會導致複製延遲。

問題二:從庫硬體比主庫差,導致複製延遲。

檢視Master和Slave的系統配置,可能會因為機器配置不當,包括磁碟I/O,CPU,記憶體等各方面因素造成複製的延遲。這一般發生在高併發大資料量寫入場景中。

問題三:慢SQL語句太多

假如一條SQL語句執行時間是20秒,那麼從執行完畢到從庫上能查到資料至少需要20秒,這樣就延遲20秒了。
一般要把SQL語句的優化作為常規工作,不斷的進行監控和優化,如果單個SQL的寫入時間長,可以修改後分多次寫入。通過檢視慢查詢日誌或show full processlist命令,找出執行時間長的查詢語句或大的事務。

問題四:主從複製的設計問題

例如,主從複製單執行緒,如果主庫寫併發太大,來不及傳送到從庫,就會導致延遲。
更高版本的MySQL可以支援多執行緒複製,入口網站則會自己開發多執行緒同步功能。

問題五:主從庫之間的網路延遲

主從庫的網絡卡,網線,連線的交換機等網路裝置都可能成為複製的瓶頸,導致複製延遲,另外,跨公網主從複製很容易導致主從複製延遲。

問題六:主庫讀寫壓力大,導致複製延遲。

主庫硬體要搞好一點,架構的前端要加buffer及快取層。

8.7.5 通過read-only引數讓從庫只讀訪問

read-only引數選項可以讓從伺服器只允許來自從伺服器執行緒或具有SUPER許可權的資料庫使用者進行更新,確保從伺服器不接受來自使用者端的非法使用者更新。
read-only引數允許資料庫更新的條件為:

  • 具有SUPER許可權的使用者可以更新,不受read-only引數影響,例如:管理員root。
  • 來自從伺服器執行緒可以更新,不受read-only引數影響,例如:前文的yunjisuan使用者。
  • 再生產環境中,可以在從庫Slave中使用read-only引數,確保從庫資料不被非法更新。

read-only引數的配置方法如下:

方法一:直接帶 --read-only引數啟動或重啟資料庫,
使用killall mysqld
mysqladmin -uroot -p123123 -S /data/3307/mysql.sock shutdown
mysqld_safe --defaults-file=/data/3307/my.cnf --read-only &

方法二:在my.cnf裡[mysqld]模組下加read-only引數重啟資料庫,配置如下:

[mysqld]
read-only

九,本節重點回顧

  1. MySQL多例項的實現原理及實戰部署
  2. MySQL主從複製的原理(面試常問)
  3. MySQL主從複製的實踐
  4. MySQL主從複製故障解決思路
  5. MySQL主從複製延遲原因及解決思路
  6. MySQL主從複製叢集,從庫備份的思想和思路
北京IT職業教育培訓中心,歡迎來校諮詢。微訊號:yinsendemogui(新增時請註明部落格園) 分類: Linux教學筆記 標籤: Linux