Mysql主从复制(MySQL Replication)
主从复制(也称 AB 复制)允许将来自一个MySQL数据库服务器(主服务器)的数据复制到一个或多个MySQL数据库服务器
主从复制是异步的,从机 复制的是 主机的 日志文件 在从机上进行 回放
基于二进制日志文件位置的主从复制
原理
- 1 主服务器上面的任何修改都会通过自己的 I/O tread(I/O 线程)保存在二进制日志 Binary log 里面。
- 2 从服务器上面也启动一个 I/O thread,通过配置好的用户名和密码, 连接到主服务器上面请求读取二进制日志,然后把读取到的二进制日志写到本地的一个Realy log(中继日志)里面
- 3 从服务器上面同时开启一个 SQL thread 定时检查 Realy log(这个文件也是二进制的),如果发现有更新立即把更新的内容在本机的数据库上面执行一遍。
实现步骤
-1 在master编辑/etc/my.conf
1 [mysqld]
2 basedir=/usr/local/lnmp/mysql
3 datadir=/data/mysql
4 socket=/data/mysql/mysql.sock
5 #skip-grant-tables
6 server-id=1
7 log-bin=mysql-bin
8
9 # include all files from the config directory
10 #
11 !includedir /etc/my.cnf.d
- 2 在master上创建一个用户
mysql> CREATE USER 'repl'@'172.25.254.%' IDENTIFIED BY 'RedHat7.6';
Query OK, 0 rows affected (0.03 sec)
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'172.25.254.%';
Query OK, 0 rows affected (0.03 sec)
- 3 配置slave
在master中
CHANGE MASTER TO
-> MASTER_HOST='172.25.254.101',
-> MASTER_USER='repl',
-> MASTER_PASSWORD='RedHat7.6',
-> MASTER_LOG_FILE='mysql-bin.000001',
-> MASTER_LOG_POS=156,
-> GET_MASTER_PUBLIC_KEY=1;
开启主从复制
mysql> start slave;
Query OK, 0 rows affected (0.01 sec)
效果
当master作出改动后 slave也做相同的动作
使用全局事务标识符(GTID)进行主从复制
原理
A global transaction identifier (GTID) is a unique identifier created and associated with each transaction committed on the server of origin (the source). This identifier is unique not only to the server on which it originated, but is unique across all servers in a given replication topology.
全局事务标识符(GTID)是创建的唯一标识符,并且与在源服务器(源)上提交的每个事务相关联。该标识符不仅对于它起源的服务器是唯一的,而且在给定复制拓扑中的所有服务器上也是唯一的。
1、当一个事务在主库端执行并提交时,产生GTID,一同记录到binlog日志中。
2、binlog传输到slave,并存储到slave的relaylog后,读取这个GTID的这个值设置gtid_next变量,即告诉Slave,下一个要执行的GTID值。
3、sql线程从relay log中获取GTID,然后对比slave端的binlog是否有该GTID。
4、如果有记录,说明该GTID的事务已经执行,slave会忽略。
5、如果没有记录,slave就会执行该GTID事务,并记录该GTID到自身的binlog,
在读取执行事务前会先检查其他session持有该GTID,确保不被重复执行。
6、在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。
实现步骤
- 1 停止服务器,修改/etc/my.conf
1 [mysqld]
2 basedir=/usr/local/lnmp/mysql
3 datadir=/data/mysql
4 socket=/data/mysql/mysql.sock
5 #skip-grant-tables
6 server-id=1
7 log-bin=mysql-bin
8 gtid_mode=ON
9 enforce-gtid-consistency=ON
10 # include all files from the config directory
11 #
12 !includedir /etc/my.cnf.d
启动数据库
- 2 配置slave
mysql> CHANGE MASTER TO
> MASTER_HOST = host,
> MASTER_PORT = port,
> MASTER_USER = user,
> MASTER_PASSWORD = password,
> MASTER_AUTO_POSITION = 1;
- 3 启动slave
mysql> START SLAVE;
Query OK, 0 rows affected (0.02 sec)
半同步复制
MySQL replication by default is asynchronous. The source writes events to its binary log and replicas request them when they are ready. The source does not know whether or when a replica has retrieved and processed the transactions, and there is no guarantee that any event will ever reach any replica. With asynchronous replication, if the source crashes, transactions that it has committed might not have been transmitted to any replica. Failover from source to replica in this case might result in failover to a server that is missing transactions relative to the source.
默认情况下,MySQL复制是异步的。源将事件写入其二进制日志,副本将在事件就绪时请求它们。源不知道副本是否或何时检索和处理了事务,并且不能保证任何事件都会到达任何副本。使用异步复制,如果源崩溃,则它提交的事务可能不会传输到任何副本。在这种情况下,从源到副本的故障转移可能会导致故障转移到缺少相对于源的事务的服务器。
使用完全同步复制,当源提交事务时,所有副本也将在源返回执行事务的会话之前提交事务。完全同步复制意味着可以随时从源故障转移到任何副本。完全同步复制的缺点是完成事务可能会有很多延迟。
半同步复制介于异步复制和完全同步复制之间。源等待直到至少一个副本接收并记录了事件(所需数量的副本是可配置的),然后提交事务。源不等待所有副本都确认接收,它仅需要副本的确认,而不是事件已在副本端完全执行并提交。因此,半同步复制可确保如果源崩溃,则它已提交的所有事务都已传输到至少一个副本。
与异步复制相比,半同步复制提供了改进的数据完整性,因为众所周知,当提交成功返回时,数据至少存在两个位置。在半同步源收到所需数量的副本的确认之前,该事务处于保留状态且未提交。
实现步骤
- 1 下载插件
#在master上
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';
#在slave上
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';
- 2 设置变量
## master端
SET GLOBAL rpl_semi_sync_master_enabled = {0|1};
SET GLOBAL rpl_semi_sync_master_timeout = N;
## slaver端
SET GLOBAL rpl_semi_sync_slave_enabled = {0|1};
永久设置 /etc/my.cnf
## master端
[mysqld]
rpl_semi_sync_master_enabled=1
rpl_semi_sync_master_timeout=1000 # 1 second
## slaver端
[mysqld]
rpl_semi_sync_slave_enabled=1
- 3 测试
确保master端 clients 不为0
使用mysqladmin插入2行数据
半异步超时时间一过就会转为异步 会造成数据不同步 解决方法是把超时时间设置为无穷大 但会损失性能