(8) MySQL主從複製架構使用方法

一. 單個數據庫服務器的缺點

數據庫服務器存在單點問題
數據庫服務器資源沒法知足增加的讀寫請求
高峯時數據庫鏈接數常常超過上限前端

二. 如何解決單點問題

增長額外的數據庫服務器,組建數據庫集羣mysql

同一集羣中的數據庫服務器須要具備相同的數據sql

集羣中的任一服務器宕機後,其它服務器能夠取代宕機服務器數據庫

三. MySQL主從複製架構

1. 主庫將變動寫入到主庫的binlog中

一些MySQL版本並不會開啓二進制日誌,因此必定要檢查是否開啓
若是剛開始沒有開啓,後面再進行開啓的話,須要重啓數據庫才能生效,並且數據庫的重啓每每會對業務形成很大的影響
儘管二進制日誌對性能有稍許的影響,因此仍是建議你們不管是否使用複製功能,都要開啓Mysql二進制日誌,由於增量備份也須要二進制日誌安全

2. 從庫的IO線程在指定位置讀取主庫binlog內容存儲到本地的中繼日誌(Relay Log)中

要完成二進制日誌的傳輸過程,MySQL會在從服務器上啓動一個工做線程,稱爲IO線程,這個IO線程會跟主數據庫創建一個普通的客戶端鏈接,而後在主服務器上啓動一個特殊的二進制轉儲線程稱爲binlogdown線程
從庫上的IO線程經過這個二進制轉儲線程來讀取主庫上的二進制事件,若是該事件追遇上主庫,則會進入sleep狀態,直到主庫發起信號通知有新事件產生時,纔會被喚醒,relay log的格式和binlog格式是徹底相同的,
可使用mysqlbinlog 來讀取relay log中的內容服務器

3. 從庫的SQL線程讀取Relay Log日誌中的內容,並在從庫中重放

sql線程所執行的事件,咱們能夠經過配置選項來決定是否要寫入到從服務器的二進制日誌中架構

目前mysql支持兩種複製類型

  1. 基於二進制日誌點的複製
  2. 基於GTID的複製(Mysql>=5.7推薦使用)

四. MySQL主從配置步驟

1. 配置主從數據庫服務器參數

有些參數配置後須要數據庫重啓才能生效,爲了避免影響數據庫的正常使用,咱們最好在服務器上線的同時就把參數都配置好
特別是master服務器的參數,更應該做爲服務器初始參數來進行配置異步

master服務器

log_bin  = /data/mysql/sql_log/mysql-bin    # 指定mysql的binlog的存放路徑 /data/mysql/sql_log,以及日誌文件名前綴mysql-bin ,
                                                                    # 若是隻是爲了啓用binlog,能夠不指定存放路徑,默認會存放到mysql的data目錄下,也就是會把日誌和數據文件存放在一塊兒
                                                                    # 之因此指定路徑分開存放,是爲了提升IO性能,因此仍是建議日誌文件和數據文件分開存放
server_id = 100    # mysql的複製集羣中經過server_id的值區分不一樣的服務器,建議使用服務器ip的後一段或後兩段的值進行配置,好比192.168.3.100,就設置爲100或2100

slave 服務器

log_bin  = /data/mysql/sql_log/mysql-bin 
server_id = 101

relay_log = /data/mysql/sql_log/relay-bin    # 指定relay_log日誌的存放路徑和文件前綴 ,不指定的話默認以主機名做爲前綴

read_only = on    #    使全部沒有server權限的用戶,在從服務器上不能執行寫操做,不論這個用戶是否擁有寫權限 (mysql5.7 可使用 super_read_only = on ,限制super用戶也不能在從服務器上執行寫操做)

skip_slave_start = on    # 在slave服務器重啓時,不會自動啓動複製鏈路。默認狀況下slave服務器重啓後,mysql會自動啓動複製鏈路,若是這個時候存在問題,則主從鏈路會中斷,因此正常狀況下,咱們應該在服務器重啓後檢查是否存在問題,而後再手動啓動複製鏈路

# 下面兩個參數是把主從複製信息存儲到innodb表中,默認狀況下主從複製信息是存儲到文件系統中的,若是從服務器宕機,很容易出現文件記錄和實際同步信息不一樣的狀況,存儲到表中則能夠經過innodb的崩潰恢復機制來保證數據記錄的一致性
master_info_repository = TABLE
relay_log_info_repository = TABLE

2. 在master服務器上建立用於複製的數據庫帳號

用於IO線程鏈接master服務器獲取binlog日誌
須要* REPLICATION SLAVE** 權限socket

create user 'repl'@'ip段' identified by 'password';
    grant replication slave on *.* to 'repl'@'ip段';

3. 備份master服務器上的數據並初始化 slave服務器數據

建議主從數據庫服務器採用相同的MySQL版本
建議使用全庫備份的方式初始化slave數據ide

採用相同版本的好處
咱們可使用全備的方式來初始化slave數據,還能夠避免不一樣版本之間的差別形成數據庫同步失敗的問題

若是咱們使用的主從複製的服務器mysql版本不一樣,則必定要注意master上的版本必定要低於slave服務器,否則同步的時候就可能出現錯誤

因爲咱們演示過程當中的mysql服務器都是使用的mysql5.7
因此咱們可使用全備的方式進行

mysqldump --master-data=2 -uroot -p -A --single-transaction -R --triggers

4. 啓動基於日誌點的複製鏈路

在slave服務器上運行

mysql命令

CHANGE MASTER TO
MASTER_HOST= 'master_host_ip',
MASTER_USER= 'repl',
MASTER_PASSWORD = 'password',
MASTER_LOG_FILE='mysql_log_file_name',
MASTER_LOG_POS=xxxxxx;

5. 啓動基於GTID的複製鏈路

GTID:全局事務ID
GTID能夠保證每個在主上提交的事務,在複製集羣中能夠生成一個惟一的ID值,要使用基於GTID的複製,咱們要在主從複製的配置文件中同時加入如下配置項

mysql配置

gtid_mode=on # 是否啓動gtid模式,啓動了此模式會在二進制日誌中會額外記錄每一個事務的GTID標識符
enforce-gtid-consistency    # 強制gtid一致性,用於保證啓動gtid後事務的安全
log-slave-updates = on    # mysql5.6必定要啓用參數,5.7能夠不啓用

mysql命令

CHANGE MASTER TO
MASTER_HOST= 'master_host_ip',
MASTER_USER= 'repl',
MASTER_PASSWORD = 'password',
MASTER_AUTO_POSITION=1;

GTID複製的限制

沒法再使用create table ... select 語句創建表,只能先create表,再insert 數據
沒法在事務中使用create temporary table 創建臨時表
沒法使用關聯更新同時更新事務表和非事務表

4和5中選一個執行便可

五. mysql主從複製演示

1. 先對主服務器進行配置

[client]
port  = 3306     # 客戶端端口號爲3306
socket = /home/mysql/data/mysql.sock

[mysqld]

# skip #
skip_name_resolve = 1
skip-external-locking =1

# GENERAL #
user = mysql   # MySQL啓動用戶
default_storage_engine = InnoDB  # 新數據表的默認數據表類型
character-set-server = utf8      #     #服務端默認編碼(數據庫級別)
socket = /home/mysql/data/mysql.sock
pid_file =  /home/mysql/data/mysqld.pid
basedir = /home/mysql    #使用該目錄做爲根目錄(Mysql安裝目錄);

port = 3306
bind-address = 0.0.0.0
log_error_verbosity = 3
explicit_defaults_for_timestamp = off
#sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#sql_mode = NO_ENGINE_SUBSTITUTION

# undo log
# innodb_undo_directory = /home.mysql/undo
# innodb_undo_tablespaces = 32

# MyISAM #
key_buffer_size =32M

# SAFETY #
max_allowed_packet    = 100M
max_connect_errors    = 1000000
sysdate_is_now    =1
#innodb = FORCE
#innodb_strict_mode = 1  

# Replice #
server-id = 100
relay_log =  /home/mysql/sql_log/mysqld-relay-bin 

#plugin-load = semisync_master.so
log_slave_updates = on
master_info_repository = TABLE
relay_log_info_repository =TABLE
# gtid_mode = on
# enforce_gtid_consistency =on
# skip-slave-start =1
#rpl_semi_sync_master_enabled = 1
#rpl_semi_sync_master_timeout=200    # 0.2 second
master_info_respository = TABLE
# gtid_mode= on
# enforce_gtid_consistency = on
# skip-slave-start = 1

# DATA STORAGE #

datadir = /home/mysql/data     #mysql 數據文件存放的目錄
tmpdir = /tmp    # MySQL存放臨時文件的目錄

# BINARY LOGGING #

log_bin = /home/mysql/sql_log/mysql-bin
max_binlog_size  = 1000M
binlog_format = row
expire_log_days = 7
sync_binlog = 1

# CACHES AND LIMITS #

tmp_table_size = 32M
max_heap_table_size = 32M
query_cache_type = 0

因爲主服務器一直在運行着,在生產環境中主服務器是不多會重啓的,若是主服務器重啓,會形成正常的業務訪問的中斷,因此在服務器啓動以前就啓動了二進制日誌
這裏不須要重啓主服務器了,因爲主服務器的默認server_id=1,咱們雖然在配置文件中更改了它的值 ,但實際運行環境中並無改變

咱們能夠查看一下當前server_id

mysql> show variables like '%server_id%';

能夠經過如下命令動態的進行修改

mysql> set global server_id = 100;

2. 再對從服務器進行配置

[client]
port  = 3306     # 客戶端端口號爲3306
socket = /home/mysql/data/mysql.sock

[mysqld]

# skip #
skip_name_resolve = 1
skip-external-locking =1

# GENERAL #
user = mysql   # MySQL啓動用戶
default_storage_engine = InnoDB  # 新數據表的默認數據表類型
character-set-server = utf8      #     #服務端默認編碼(數據庫級別)
socket = /home/mysql/data/mysql.sock
pid_file =  /home/mysql/data/mysqld.pid
basedir = /home/mysql    #使用該目錄做爲根目錄(Mysql安裝目錄);

port = 3306
bind-address = 0.0.0.0
log_error_verbosity = 3
explicit_defaults_for_timestamp = off
#sql_mode = NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
#sql_mode = NO_ENGINE_SUBSTITUTION
read_only = on

# undo log
# innodb_undo_directory = /home.mysql/undo
# innodb_undo_tablespaces = 32

# MyISAM #
key_buffer_size =32M

# SAFETY #
max_allowed_packet    = 100M
max_connect_errors    = 1000000
sysdate_is_now    =1
#innodb = FORCE
#innodb_strict_mode = 1  

# Replice #
server-id = 101
relay_log =  /home/mysql/sql_log/mysqld-relay-bin 

#plugin-load = semisync_master.so
log_slave_updates = on
master_info_repository = TABLE
relay_log_info_repository =TABLE
# gtid_mode = on
# enforce_gtid_consistency =on
# skip-slave-start =1
#rpl_semi_sync_master_enabled = 1
#rpl_semi_sync_master_timeout=200    # 0.2 second
master_info_respository = TABLE
# gtid_mode= on
# enforce_gtid_consistency = on
# skip-slave-start = 1

# DATA STORAGE #

datadir = /home/mysql/data     #mysql 數據文件存放的目錄
tmpdir = /tmp    # MySQL存放臨時文件的目錄

# BINARY LOGGING #

log_bin = /home/mysql/sql_log/mysql-bin
max_binlog_size  = 1000M
binlog_format = row
expire_log_days = 7
sync_binlog = 1

# CACHES AND LIMITS #

tmp_table_size = 32M
max_heap_table_size = 32M
query_cache_type = 0

修改完從服務器配置後,重啓mysql服務器

若是使用的是mysql5.7版本的須要注意
mysql5.7增長了server-uuid值,默認狀況下載auto.cnf文件中,若是是使用的鏡像的方式安裝,可能你們的uuid同樣 ,因此須要把auto.cnf文件刪除掉。mysql重啓後會自動從新生成uuid的值,這樣就能夠保證不一樣服務器上的mysql實例的uuid的值是不同的

若是server-uuid的值相同,主從複製會出現問題

以上咱們就完成了主從複製的配置,接下來咱們要在主服務器上創建複製帳號

3. 在mysql主服務器上創建mysql複製帳號

mysql> create user 'dba_repl'@'192.168.3.%' identified by '123456';

mysql> grant replication slave on *.* to 'dba_repl'@'192.168.3.%';

創建好複製帳號之後

4. 經過mysql主服務器上的全備初始化從服務器上數據

進行全備

[root@localhost data]# cd /data/db_backup/
[root@localhost db_backup]#  mysqldump -uroot -p --master-data=1 --single-transaction --routines --triggers --events  --all-databases > all.sql
Enter password:

將其拷貝到從服務器上

[root@localhost db_backup]# scp all.sql root@192.168.3.101:/root

在從服務器上恢復備份進行初始化

[root@Node2 ~]# mysql -uroot -p < all.sql

初始化完成後,準備

5. 從服務器進行基於日誌點的複製鏈路的配置

mysql> change master to master_host='192.168.3.100',
        -> master_user='dba_repl',
        -> master_password='123456',
        ->MASTER_LOG_FILE='mysql-bin.000017',MASTER_LOG_POS=663;

MASTER_LOG_FILE和MASTER_LOG_POS的值從全備文件中的CHANGE MASTER中獲取

以上覆制鏈路的配置完成

啓動slave

mysql> start slave;

檢查是否啓動成功狀態

mysql> show slave status \G

顯示

Relay_Master_Log_File: mysql-bin.000017
Slave_IO_Running:Yes
Slave_SQL_Running: Yes

說明啓動成功了,能夠在主服務器上插入數據,在從服務上查看數據是否同步過來了

六. 主從複製的一些缺點

雖然主從複製,增長了一個數據庫副本,從數據庫和主數據庫的數據最終會是一致的
之因此說是最終一致,由於mysql複製是異步的,正常狀況下主從複製數據之間會有一個微小的延遲
經過這個數據庫副本看似解決了數據庫單點問題,但並不完美
由於這種架構下,若是主服務器宕機,須要手動切換從服務器,業務中斷不能忍受,不能知足應用高可用的要求

若是才能解決當master服務器宕機後,前端應用自動切換連接呢?

下節再進行學習

相關文章
相關標籤/搜索