1、主从复制的工做原理
mysql
Mysql在Master与slave之间实现整个复制的过程由3个线程来完成的,
linux
其中两个线程(SQL线程和IO线程)在 Slave端,
sql
另一个线程(IO)在Master端
数据库
要实现Mysql的复制必须首先打开Master端的binary log(也就是二进制日志)不然没法实现.vim
Mysql复制基本过程以下:缓存
(1)Slave上面的IO 线程连接上Master,而且请求指定日志文件的位置(或者 从开始的日志以后的日志内容)
服务器
(2)Master接收到来自Slave的IO线程请求后,经过负责复制的IO线程根据这个请求信息指定日志的位置后,
多线程
把这个信息返回给Slave的IO线程(返回的信心当中除了日志所包含的信息外,还包括了Master端的二进制文件名称和 二进文件的位置)架构
(3)Slave的IO线程接收到Master端的返回信息以后,将日志内容一次写入slave端的Relay log文件,(mysql-relay-bin.xxx)当中,而且读取到Master端的bin-log文件和位置记录, 记录到master-info文件当中,以便下一次可以清楚的告诉Master我须要从某个bin-log的哪一个位置开始日后的内容,请发给我。
(4)、Slave的SQL线程检测Relay log中心增长了内容后,立刻解析Master二进制文件中的内容,而且执行里面的Query语句. 数据的更新 只能从主服务器向从服务器更新,而不能反过来进行。
socket
当master主服务器中数据有更新时,会先将数据的更新写入本身的数据库中,
将更新的语句写入二进制日志文件里面。
对于从服务器,首先启动IO线程 向主服务器进行二进制日志的复制到本身的中继日志里面,
从服务器复制了二进制日志内容以后并不会直接更新本身的数据库,要首先写入本身的中继Relay log日志里面,
而后从服务器使用SQL线程从中继日志里面解析二进制日志去更新本身的数据库。
注意:1. 从服务器必须启动两个线程
2. 不会直接更新本身的数据库,而是写入本身的中继日志
3. 单向更新
2、Mysql的优势
1.若是主服务器出现问题,能够快速切换到从服务器提供的服务
2.能够在从服务器上执行查询操做,下降主服务器的访问压力
3.能够在从服务器上执行备份,以免备份期间影响主服务器的服务
==============================================
注意error:
(1)进行主从复制,主从服务器的时间要同步
# date -s '2015-07-22'
# date
(2) 关闭防火墙
# iptables -F
# vim /etc/selinux/config
(3) 初始化可能会遇到错误。不要惧怕。把数据库文件下的全部文件都删除掉。datadir=/database/mydata
从新初始化
(4)当启动mysql时,出现without PID时,cat /etc/my.cnf --> 错误日志的位置 -->查看错误日志
# ps -ef | grep mysqld
# kill -p PID
(5 )不能受权了一次没有成功,又继续受权,会混乱的。要把第一次受权的用户删掉
再从新受权用户。
=================================
为何MySQL要作主从复制(读写分离)?
通俗来说,若是对数据库的读和写都在同一个数据库服务器中操做,业务系统性能会下降。
为了提高业务系统性能,优化用户体验,能够经过作主从复制(读写分离)来减轻主数据库的负载。
并且若是主数据库宕机,可快速将业务系统切换到从数据库上,可避免数据丢失。
主从复制有两种方式:
基于日志(binlog)
基于GTID(全局事务标示符)
======================================
一、基于日志的主从复制
主服务器:10.0.199.1
从服务器:10.0.199.2
(1)主服务器配置
[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
user = mysql
innodb_buffer_pool_size = 128M
log_bin = master-log
max_binlog_size = 64M
binlog_format = mixed
basedir = /usr/local/mysql
datadir = /database/mydata
port = 3306
server_id = 1
socket = /tmp/mysql.sock
log_error = /database/mydata/server1.err
character_set_server = utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
数据库初始化
# service mysqld stop
# cd /usr/local/mysql
# ./scripts/mysql_install_db --user=mysql --datadir=/database/mydata
# service mysqld start
给从服务器受权
mysql> grant replication slave on *.* to 'admin'@'10.0.199.2' identified by 'aixocm';
mysql> flush privileges;
mysql> show master status\G
mysql> select user,host,password from mysql.user;
(2)从服务器配置
[client]
port = 3306
socket = /tmp/mysql.sock
[mysqld]
user = mysql
innodb_buffer_pool_size = 128M
log_bin = slave-log
max_binlog_size = 64M
log_slave_updates = on
binlog_format = mixed
relay_log = relay-bin
basedir = /usr/local/mysql
datadir = /database/mydata
port = 3306
server_id = 2
socket = /tmp/mysql.sock
log_error = /database/mydata/server1.err
character_set_server = utf8
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES
数据库初始化
# service mysqld stop
# cd /usr/local/mysql
# ./scripts/mysql_install_db --user=mysql --datadir=/database/mydata
注意:初始化可能会遇到错误。不要惧怕。把数据库文件下的全部文件都删除掉。datadir=/database/mydata
从新初始化
# service mysqld start
设置主服务器相关信息
mysql> show master status\G; (在主服务器端)
mysql> change master to master_host='10.0.199.1',master_user='admin',master_password='aixocm',master_log_file='m aster-log.000011',master_log_pos=565,master_port=3306;
# master_log_pos=565 //意思把565之后的日志都同步到从服务器上。也能够设置为1 或者其余数字位置。
mysql> start slave;
mysql> show slave status\G
线程都必须为yes,同步数据才会成功。
若是主服务器 进行了增删改操做,在从服务器上show slave status\G出现了以下错误:
解决办法:mysql> reset master; (在主服务器上删除全部的日志datadir=/database/mydata)
mysql> stop slave;
(3)二进制日志操做
mysql日志分为4种:
(1)二进制日志
(2)错误日志
(3)慢 查询日志
(4)通用查询日志
# vim /etc/profile
export PATH=$PATH:/usr/local/mysql/bin
由于:全部和mysql有关的命令都在mysql安装目录下的bin下 (mysqlbinlog命令)
# source /etc/profile
# mysqlbinlog master-log.000001
# mysqlbinlog --start-datetime='2015-07-13 7:10:0' master-log.000003
# mysqlbinlog --start-datetime='2015-07-13 7:10:0' --stop-datetime='2015-07-13 7:33:0' master-log.000003
# mysqlbinlog --start-position=330 master-log.000003
# mysqlbinlog --start-position=330 --stop-position=1100 master-log.000003
# mysqlbinlog --start-position=330 --stop-position=1100 master-log.000003 | mysql -u root
\\恢复指定二进制日志的 内容
mysql> show master logs;
mysql> show binary logs;
mysql> show binlog events in 'master-log.000003' limit 20;
mysql> show binlog events in 'master-log.000003' from 409 limit 10;
mysql> purge master logs to 'master-log.000002'; \\删除指定编号以前的日志
mysql> purge master logs before '2015-07-22 08:00:00';
(4)设置忽略的数据库
注意:修改了配置文件以后,必需要像上面同样都要进行数据初始化,主服务器受权刷新 从服务器change
主服务器设置
binlog_do_db = sxjy \\记录二进制日志的数据库
binlog_ignore_db = test \\不记录二进制日志的数据库
binlog_ignore_db = teach
从服务器设置
replicate_do_db = sxjy \\设置默认进行二进制日志复制的数据库
replicate_ignore_db = test \\不对test数据库进行二进制日志复制
replicate_ignore_db = teach
replicate_ignore_db = mysql
replicate_ignore_db = information_schema
replicate_do_table = sxjy.stu \\设置进行更新的表
replicate_ignore_table = sxjy.class \\不进行更新的表
从服务器建议设置
replicate_ignore_db = test \\不对test数据库进行二进制日志复制
replicate_ignore_db = mysql
replicate_ignore_db = information_schema
replicate_wild_do_table = sxjy.stu \\复制指定的数据库或表的二进制日志
replicate_wild_do_table = sxkj.%
replicate_wild_ignore_table = sxjy.class \\不复制指定的数据库或表的二进制日志
练习:先搭建一台mysql数据库服务器,不启用二进制日志,而后启动服务器,先建立一个sxjy数据库,
在sxjy数据库下建立stu和teach两个表,字段本身添加3-4个,而后插入4-5个记录。而后将
服务器改成主从结构,要求原先的服务器作主服务器,且在从服务器上要有主服务器上原来的数
主从结构搭建好后,之后添加的数据可以自动同步到从服务器,主从服务器数据要彻底一致。
解析: 主服务器:# mysqldump -uroot --opt --database sxjy > sxjy.sql
将新建的sxjy数据库导出。而后创建了主从复制以后,再将sxjy.sql导入到从服务器内。
二、基于GTID的mysql主从复制
(1) TID:Transaction ID,事务的ID号:也就是说在mysql复制中每个事务都有本身的ID号(随机数)
(2) GTID:Global Transaction ID,全局事务ID
在整个事务架构中每个事务ID号是全局惟一的,
不止是在一个节点上而是整个主从复制架构中每任何两个事务的ID号都不会相同。
(3) 全局事务ID是怎么生成的?
简 单来说是由mysql服务器自动管理的,在mysql5.6之后每个mysql服务器都有一个全局惟一的ID号叫作uuid,通用惟 一识别码 (Universally Unique Identifier),而GTID就是由当前节点的UUID(一个128位的随机数)和为当前节点生成的随机数(TID)组成的,所以只要UUID不一样 再在此基础上保证事务ID不一样就保证全局不同了。
(4) 全局事务ID有何用处?
简单来说GTID可以保证让一个从服务器到其余的从服务器那里实现数据复制并且可以实现数据整合的。GTID在分布式架构中能够保证数据的一致性。从而也实现了mysql的高可用性。
(5) GTID相关操做:
默认状况下将一个事务记录进二进制文件时将首先记录它的GTID并且GTID和事务相关信息一并要发送给从服务器由从服务器在在本地应用认证可是绝对不会改变原来的事务ID号。
(6) GTID的组成部分:
前面是server_uuid:后面是一个序列号
例如:server_uuid:sequence number
7800a22c-95ae-11e4-983d-080027de205a:10
UUID:每一个mysql实例的惟一ID,因为会传递到slave,因此也能够理解为源ID。
Sequence number:在每台MySQL服务器上都是从1开始自增加的序列,一个数值对应一个事务。
(7) GTID的工做原理:
一、master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。
二、slave端的i/o 线程将变动的binlog,写入到本地的relay log中。
三、sql线程从relay log中获取GTID,而后对比slave端的binlog是否有记录。
四、若是有记录,说明该GTID的事务已经执行,slave会忽略。
五、若是没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
六、在解析过程当中会判断是否有主键,若是没有就用二级索引,若是没有就用所有扫描。
要点:
一、slave在接受master的binlog时,会校验master的GTID是否已经执行过(一个服务器只能执行一次)。
二、为了保证主从数据的一致性,多线程只能同时执行一个GTID。
(1)可以基于数据库进行多线程复制(要求2个或2个以上的数据库进行同步)
(2)可以自动判断要复制的位置
注意:修改了配置文件以后,必需要像上面同样都要进行数据初始化,主服务器受权刷新 从服务器change
注意:初始化可能会遇到错误。不要惧怕。把数据库文件下的全部文件都删除掉。datadir=/database/mydata
从新初始化
binlog-format:二进制日志的格式,有row、statement和mixed
在上面的基于日志的主从复制配置文件中再加入如下内容:
主服务器配置
bin_log = master-log
log_slave_updates = on
gtid_mode = on \\开启GTID模式
enforce_gtid_consistency = on \\强制GTID的一致性
master_info_repository =TABLE \\主服务器信息的记录方式(TABLE或FILE)
relay_log_info_repository = TABLE \\中继日志信息的记录方式
sync_master_info = 1 \\同步主数据库信息, 确保服务器崩溃时无信息丢失
slave_parallel_workers = 4 \\从服务器的sql线程数,和要复制的数据库的个数 相同
binlog_checksum =CRC32 \\二进制日志的校验方式
master_verify_checksum = 1 \\主服务器启用校验
slave_sql_verify_checksum = 1 \\从服务器启用校验
binlog_rows_query_log_events = 1 \\二进制日志详细记录事件 ,可下降故障排除的复杂度
report_port = 3306 \\提够复制的报告端口,和数据库端口一致
report_host = 10.0.199.1 \\提供复制报告的主机,设为本机地址
mysql> grant replication slave on *.* to 'admin'@'10.0.199.2' identified by 'aixocm';
mysql> flush privileges;
mysql> show master status\G
从服务器配置
bin_log = master-log
log_slave_updates = on
gtid_mode = on \\开启GTID模式
enforce_gtid_consistency = on \\强制GTID的一致性
master_info_repository =TABLE \\主服务器信息的记录方式(TABLE或FILE)
relay_log_info_repository = TABLE \\中继日志信息的记录方式
sync_master_info = 1 \\同步主数据库信息
slave_parallel_workers = 4 \\从服务器的sql线程数,和要复制的数据库的个数 相同
binlog_checksum =CRC32 \\二进制日志的校验方式
master_verify_checksum = 1 \\主服务器启用校验
slave_sql_verify_checksum = 1 \\从服务器启用校验
binlog_rows_query_log_events = 1 \\二进制日志详细记录事件
report_port = 3306 \\提够复制的报告端口,和数据库端口一致
report_host = 10.0.199.2 \\提供复制报告的主机,设为本机地址
slave_skip_errors = all
\\若是在主服务器的某个表中插入4,'张三','man' ,而又在从插入4,'王五','woman' 相冲突。
跳过此error,从而不影响下面数据的同步
(或slave_skip_errors = 1062,1756,2003)
mysql> change master to master_host='10.0.199.1',master_user='admin',
master_password='aixocm',master_auto_position=1;
mysql> start slave;
必须所有为yes才会成功
mysql> show processlist\G
mysql> show status like 'thread%';
三、双主复制
注意:互为主从。两边都要相互进行数据初始化受权刷新change
在基于日志的主从复制配置文件上添加如下内容:
第一台服务器设置(10.0.199.1)
auto_increment_increment = 2 # 数据表记录的自增量,通常等于服务器的数量
auto_increment_offset = 1 # 数据表记录每次的递增量,第一台为1,第二台为2,...
sync_binlog = 0 # 二进制日志写入磁盘的方式(1表示当即写入磁盘 0表示先缓存再写入磁盘)
replicate_same_server_id = 0 # 防止mysql循环更新
数据库初始化
# service mysqld stop
# cd /usr/local/mysql
# ./scripts/mysql_install_db --user=mysql --datadir=/database/mydata
# service mysqld start
第二台服务器设置(10.0.199.2)
auto_increment_increment = 2 # 数据表记录的自增量,通常等于服务器的数量
auto_increment_offset = 2 # 数据表记录每次的递增量,第一台为1,第二台为2,...
sync_binlog = 0 # 二进制日志写入磁盘的方式(1表示当即写入磁盘 0表示先缓存再写入磁盘)
replicate_same_server_id = 0 # 防止mysql循环更新
数据库初始化
# service mysqld stop
# cd /usr/local/mysql
# ./scripts/mysql_install_db --user=mysql --datadir=/database/mydata
# service mysqld start
10.0.199.1做主服务器 :
主:mysql> grant replication slave on *.* to 'repuser'@'10.0.199.2' identified by 'aix ocm';
mysql> flush privileges;
从:mysql> change master to master_host='10.0.199.1',master_user='repuser',
master_password='aixocm',master_auto_position=1;
mysql> start slave;
mysql> show slave status\G
10.0.199.2做主服务器:
主:mysql> grant replication slave on *.* to 'admin'@'10.0.199.1' identified by 'aixocm';
mysql> flush privileges;
从:mysql> change master to master_host='10.0.199.2',master_user='admin',
master_password='aixocm',master_auto_position=1;
mysql> start slave;
mysql> show slave status\G
测试:双服务器上都插入数据或者更新数据,查看对方服务器数据是否有改变。