MySQL主从复制虽好,能完美解决数据库单点问题吗?
點擊上方“朱小廝的博客”,選擇“設為星標”
回復”1024“獲取獨家整理的學習資料
一、單個數據庫服務器的缺點
數據庫服務器存在單點問題;
數據庫服務器資源無法滿足增長的讀寫請求;
高峰時數據庫連接數經常超過上限。
二、如何解決單點問題
增加額外的數據庫服務器,組建數據庫集群;
同一集群中的數據庫服務器需要具有相同的數據;
集群中的任一服務器宕機后,其它服務器可以取代宕機服務器。
三、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支持兩種復制類型:
基于二進制日志點的復制
基于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或2100slave 服務器:
log_bin??=?/data/mysql/sql_log/mysql-bin? server_id?=?101relay_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?=?TABLE2、在master服務器上創建用于復制的數據庫賬號
用于IO線程連接master服務器獲取binlog日志,需要* REPLICATION SLAVE** 權限:
create user 'repl'@'ip段' identified by 'password';
? ? grant replication slave on *.* to 'repl'@'ip段';
3、備份master服務器上的數據并初始化slave服務器數據
建議主從數據庫服務器采用相同的MySQL版本;
建議使用全庫備份的方式初始化slave數據。
采用相同版本的好處:
我們可以使用全備的方式來初始化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復制是異步的,正常情況下主從復制數據之間會有一個微小的延遲。
通過這個數據庫副本看似解決了數據庫單點問題,但并不完美:因為這種架構下,如果主服務器宕機,需要手動切換從服務器,業務中斷不能忍受,不能滿足應用高可用的要求。
作者:聽風
來源:http://1t.click/VGR
如大家對內容有更多想法及建議,歡迎留言交流~
想知道更多?掃描下面的二維碼關注我
加技術群入口(備注:技術):>>>Learn More<<
免費資料入口(備注:1024):>>>Learn More<<
免費星球入口:>>>Free<<<
內推通道>>>>
今天開始到9月7日,當當開學季促銷,滿600減300,用我的優惠碼還可以減50,相當于250買600的書,支持全品類。結算的時候用優惠碼?TMWCP4?即可。
點個"在看"唄^_^
總結
以上是生活随笔為你收集整理的MySQL主从复制虽好,能完美解决数据库单点问题吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 很现实、很暴力的面试法则 —— 来自招聘
- 下一篇: 有理有据!为什么String选择数字31