MySQL主从复制是一种常见的数据库架构设计,用于提高系统的可用性、性能和可靠性。在主从复制中,有一个主数据库(Master)和一个或多个从数据库(Slave)。主数据库负责处理写操作和更新数据,而从数据库复制主数据库的数据,用于读操作和备份。
为什么进行主从复制:为保证数据完整性
谁复制谁:从(salve)角色复制主(Master)角色的数据
数据放在哪:二进制日志文件中记录完整sql
主服务器上的应用程序执行数据更改操作(INSERT、UPDATE、DELETE等)。
主服务器将这些更改记录到自己的binlog中。
从服务器的I/O线程连接到主服务器的binlog,将事件读取到从服务器的relay log中。
从服务器的SQL线程读取relay log中的事件,并在从服务器上执行相同的数据更改操作,将数据同步到从服务器上。
这个流程实现了主从数据库的数据同步,使得从服务器上的数据与主服务器保持一致,同时也提供了冗余和负载均衡的好处。
以下是MySQL主从复制的基本原理:
Binlog(二进制日志): 主数据库记录所有的写操作,将这些操作以二进制格式保存在binlog中。
dump 线程是主数据库(Master)中的一个线程,负责将二进制日志(binlog)中的内容发送给从数据库(Slave)。
I/O Thread(输入输出线程): 从数据库上运行的I/O线程监听连接到主数据库,读取binlog中的二进制日志。
Relay Log(中继日志): 从数据库将主数据库的binlog内容写入自己的relay log中。
SQL Thread(SQL线程): 从数据库上运行的SQL线程读取relay log中的内容,并在从数据库上执行相应的SQL语句,以更新从数据库的数据。
通过这个过程,从数据库的数据保持与主数据库同步,实现了主从复制。这种架构有以下优点:
高可用性: 如果主数据库发生故障,可以快速切换到从数据库,提高系统的可用性。
读写分离: 读操作可以分流到从数据库,分担主数据库的负载,提高系统性能。
备份: 从数据库可以用于实时备份,而不影响主数据库的性能。
为了实现MySQL主从复制,需要进行一些配置步骤,如在主数据库上开启binlog、配置从数据库连接等。具体的配置步骤可以根据数据库版本和具体需求而有所不同。
?
在异步复制中,主节点(master)将写操作的更改记录到二进制日志(binary log),然后从节点(slave)定期连接主节点,从主节点的二进制日志中读取这些更改,并将其应用到自己的数据库中。主要特点包括:
延迟: 从节点不会立即复制主节点的变更,而是在一定时间间隔后才进行复制。这可能导致主从之间存在一定程度的延迟。
可用性: 异步复制不会阻塞主节点的写操作,因此主节点的性能通常不受从节点复制进程的影响。
数据一致性: 由于延迟的存在,从节点的数据可能在某些情况下稍微落后于主节点。
同步复制要求主节点等待至少一个从节点确认已经接收并应用了写操作的更改,然后才会提交这个操作。主要特点包括:
严格一致性: 确保所有写操作都在至少一个从节点上完成后才被认为是成功的,因此可以保证主从节点之间的数据完全一致。
性能影响: 由于主节点需要等待至少一个从节点的确认,这可能对主节点的写入性能产生影响。如果从节点延迟或不可用,主节点的写入可能会受到阻塞。
选择使用异步复制还是同步复制通常取决于系统的需求和特定的应用场景。异步复制对于那些对实时性要求不是特别高,但更关注性能和可用性的系统可能更适合。而同步复制则更适用于对数据一致性和完整性要求非常高的场景。
MySQL 提供了不同的配置选项和参数,可以根据实际需求设置主从复制的模式和相关参数,以满足系统的特定需求。
半同步复制介于异步复制和同步复制之间。在半同步复制中,主节点会等待至少一个从节点确认已经接收了写操作的变更,但不需要等待所有从节点。这可以在一定程度上提高数据一致性,同时减轻了主节点性能的影响。
Binlog(二进制日志)
二进制日志(Binary Log),通常简称为 Binlog,是 MySQL 中用于记录数据库中发生更改的一种日志。它记录了数据库的写操作,如插入、更新和删除操作,以二进制格式保存。 Binlog 在 MySQL 主从复制、数据恢复和数据库备份等方面起到重要的作用。
以下是 Binlog 的基本原理和作用:
记录写操作: Binlog 主要用于记录数据库中的写操作。每当执行了一次写操作(例如插入、更新、删除),MySQL 就会将相应的信息记录到 Binlog 中。
格式: Binlog 记录的内容是以二进制格式保存的,而非可读的 SQL 语句。这样可以减小日志文件的大小,并提高写入和读取的效率。
用途: Binlog 的主要用途之一是支持主从复制。在主数据库上产生的 Binlog 文件会被传输到从数据库,从数据库通过读取 Binlog 文件来复制主数据库的写操作,实现数据的同步。此外,Binlog 还可以用于数据恢复和数据库备份。
存储位置: Binlog 文件通常存储在 MySQL 数据目录下的 binlog
子目录中。每个 Binlog 文件都有一个唯一的文件名,例如 mysql-bin.000001
,并包含一系列的事件,每个事件代表一个写操作。
配置: 在 MySQL 的配置文件中,可以通过配置参数来控制 Binlog 的开启和设置相关参数,例如指定 Binlog 的存储格式、指定 Binlog 文件的最大大小等。
事件类型: Binlog 记录的事件类型包括 Statement 格式和 Row 格式。Statement 格式记录的是 SQL 语句的文本,而 Row 格式记录的是每一行记录的变更。
总体而言,Binlog 在 MySQL 中扮演了重要的角色,为主从复制、数据备份和恢复等提供了关键的支持。
dump 线程
dump
线程是主数据库(Master)中的一个线程,负责将二进制日志(binlog)中的内容发送给从数据库(Slave)。具体来说,dump
线程的作用如下:
Binlog Dump: 主数据库上的 dump
线程负责将主数据库的二进制日志内容发送给从数据库。这是通过与从数据库的 I/O 线程建立连接,将 binlog 中的数据传输给从数据库。
数据传输: dump
线程负责将主数据库的 binlog 中的更新操作(写入、更新、删除等)发送给从数据库,以确保从数据库能够及时复制主数据库的变更。
传递位置信息: dump
线程还会将当前的二进制日志的位置信息(例如,binlog 文件名和文件中的位置)传递给从数据库的 I/O 线程。这样,从数据库的 I/O 线程知道从哪里开始读取 binlog 数据。
总的来说,dump
线程在主从复制中起到了传输主数据库变更操作的作用。它与从数据库的 I/O 线程协同工作,确保从数据库能够及时、准确地获取主数据库中的变更数据,从而保持主从数据库的一致性。
需要注意的是,这里提到的 dump
线程是主数据库上的线程,在从数据库上,对应的是 I/O 线程,它负责接收主数据库发送的 binlog 数据。整个过程中的配合工作,确保了主从复制的正常运行。
I/O Thread(输入输出线程)
I/O 线程(Input/Output Thread)是 MySQL 主从复制中的一个重要组成部分,负责在主数据库和从数据库之间传输二进制日志(Binlog)的数据。主要有两个线程参与主从复制的 I/O 操作:主数据库上的 I/O 线程和从数据库上的 I/O 线程。
以下是 I/O 线程的主要作用和原理:
主数据库上的 I/O 线程: 在主数据库上运行的 I/O 线程负责将主数据库的二进制日志(Binlog)发送给从数据库。它通过监听主数据库上的二进制日志文件的变化,实时地将变更的数据传输到从数据库。
从数据库上的 I/O 线程: 在从数据库上运行的 I/O 线程则负责接收主数据库传输过来的二进制日志数据。它建立与主数据库上 I/O 线程的连接,读取主数据库的 Binlog 数据,然后写入从数据库的中继日志(Relay Log)中。
I/O 线程的协作: 主数据库上的 I/O 线程和从数据库上的 I/O 线程之间会建立一个长连接,通过这个连接进行数据传输。主数据库的 I/O 线程将 Binlog 数据传输给从数据库的 I/O 线程,从数据库的 I/O 线程则负责接收和处理这些数据。
同步位置信息: 主数据库的 I/O 线程会将当前传输的 Binlog 文件名和文件中的位置信息传递给从数据库的 I/O 线程。这样从数据库的 I/O 线程知道从哪个位置开始读取 Binlog 数据,确保同步的准确性。
通过 I/O 线程的协作,实现了主从数据库之间的数据同步。这种架构具有高可用性和读写分离的优势。主数据库负责写操作,而从数据库通过复制主数据库的 Binlog 内容来保持数据一致性。需要注意的是,主从复制是异步的,可能存在一定的数据延迟。
Relay Log(中继日志)
中继日志(Relay Log)是 MySQL 主从复制中从数据库(Slave)上的一个重要组成部分,用于存储主数据库传输过来的二进制日志(Binlog)数据。中继日志是从数据库上的 I/O 线程接收 Binlog 数据后写入的一个本地日志文件。
以下是中继日志的主要作用和一些关键特点:
接收主数据库的Binlog数据: 从数据库上的 I/O 线程负责接收主数据库传输过来的 Binlog 数据,然后将这些数据写入中继日志。
保存在本地文件中: 中继日志以文件的形式存储在从数据库上,通常存储在 MySQL 数据目录下的 relaylog
子目录中。每个中继日志文件都有一个唯一的文件名,例如 relay-bin.000001
。
用于 SQL 线程执行: 从数据库上的 SQL 线程会读取中继日志的内容,然后执行其中的 SQL 语句。通过这个过程,从数据库实现了与主数据库的数据同步。
同步位置信息: 中继日志中还包含了位置信息,即从数据库 I/O 线程从主数据库读取的 Binlog 文件名和文件中的位置信息。这些信息是为了确保从数据库能够从正确的位置开始读取 Binlog 数据。
可用于故障恢复: 中继日志的保存可以在从数据库发生故障时用于恢复数据。如果从数据库在执行 SQL 线程过程中发生错误,可以通过查看中继日志来确定在哪里发生了问题。
总体而言,中继日志在主从复制中起到了关键的角色。它是主数据库变更操作的本地存储,通过它,从数据库能够按顺序执行相应的 SQL 语句,实现数据的同步。
SQL Thread(SQL线程)
SQL 线程(SQL Thread)是 MySQL 主从复制中从数据库(Slave)上的一个关键组件,其主要责任是读取中继日志(Relay Log)中的数据并执行相应的 SQL 语句,从而实现与主数据库的数据同步。
以下是 SQL 线程的主要作用和一些关键特点:
读取中继日志: SQL 线程负责从中继日志中读取数据。中继日志中包含了主数据库传输过来的二进制日志(Binlog)的内容,SQL 线程通过读取这些数据来获取主数据库的写操作。
执行 SQL 语句: SQL 线程读取到中继日志中的数据后,会解析其中的 SQL 语句,并在从数据库上执行相应的操作,包括插入、更新、删除等。
同步位置信息: SQL 线程会不断地更新自己读取的中继日志的位置信息,以便下一次读取时从正确的位置开始。这些位置信息包括中继日志的文件名和文件中的位置。
同步过程中的并发处理: SQL 线程会并发地执行从中继日志中读取到的 SQL 语句,以提高同步的效率。这意味着多个写操作可以同时在从数据库上执行,从而更迅速地跟上主数据库的变更。
错误处理: 如果在执行 SQL 语句的过程中发生错误,SQL 线程会尝试进行错误处理。这可能包括跳过出错的语句、记录错误信息等。错误处理的方式可以通过配置进行调整。
总体而言,SQL 线程是 MySQL 主从复制中非常重要的一环,它负责将主数据库的变更操作在从数据库上再现,从而保持两者的数据一致性。SQL 线程与 I/O 线程共同协作,完成主从复制的整个数据同步过程。
主从复制延迟是指从主数据库到从数据库的数据同步存在一定的时间差,导致从库的数据不是实时与主库同步。这种延迟可能由多种原因引起,以下是一些常见的原因和解决方法:
通过综合考虑这些因素并采取相应的优化措施,可以有效减小主从复制的延迟问题。
MySQL读写分离是通过在数据库系统中同时使用主库(写操作)和多个从库(读操作)的架构来提高系统性能和容错性的一种方法。这种架构可以在高并发的情况下提高查询性能,分担主库的压力,同时提高系统的可用性。下面是MySQL读写分离的基本原理和实现步骤:
选择一个主数据库(Master)来处理所有的写操作(INSERT、UPDATE、DELETE)。
创建一个或多个从数据库(Slave),这些从数据库是主数据库的复制品,它们的数据与主数据库保持同步。
通过以上步骤,读写分离能够提高数据库系统的性能,因为读操作可以并行在多个从数据库上进行,从而提高并发处理能力,同时主数据库可以专注于处理写操作,保障数据的一致性
在从库上配置连接主库的信息,包括主库的IP地址、用户名、密码等。
启动从库的I/O线程和SQL线程,使得从库可以同步主库的数据变更。
在应用程序的数据库连接配置中,将读操作指向从库,写操作指向主库。
对于一些只涉及读操作的查询,可以通过从库来分担主库的负担。
提高系统性能,分担主库的压力,增加读操作的并发性。
增强系统的容错性,即使主库发生故障,从库仍然可以提供读服务。
读写分离并不适用于所有场景,特定的业务需求和数据一致性要求需要进行综合考虑。
对于写入后立即读取的场景,可能需要在主库上执行完写操作后立即读取,以确保数据的一致性。
需要定期监控主从库同步状态,及时处理同步延迟等问题。
通过合理配置和管理,MySQL读写分离可以有效提升系统性能和可用性。
Master服务器:192.168.41.11 mysql5.7
Slave1 服务器:192.168.41.31 mysql5.7
Slave2 服务器:192.168.41.32 mysql5.7
Amoeba 服务器:192.168.41.10 jdk1.6、Amoeba
客户端 服务器:192.168.41.21 mysql
systemctl stop firewalld
systemctl disable firewalld
setenforce 0
在搭建 MySQL 主从复制时,设置主从服务器时间同步是非常重要的。时间同步的目的是确保主从服务器之间的时间保持一致,这对于数据库同步和数据一致性非常关键。以下是时间同步的几个重要原因:
确保事件顺序一致性: MySQL 主从复制是基于二进制日志的,主服务器将更新事件写入二进制日志,然后从服务器通过读取主服务器的二进制日志来执行相同的更新操作。如果主从服务器的时间不同步,可能导致事件的时间戳不准确,从而影响到复制的正确性和一致性。
避免数据延迟: 时间同步有助于减小主从服务器之间的时间差,避免由于时间差引起的数据延迟。如果从服务器的时间比主服务器慢,可能会导致从服务器执行的操作相对较早,从而引起数据不一致。
防止冲突和数据错误: 如果主从服务器的时间不同步,可能导致在相同时间点上执行的事务在主从服务器上出现冲突,从而引发数据错误。通过时间同步,可以确保事务在主从服务器上按照相同的时间顺序执行。
为了实现时间同步,可以采用网络时间协议(NTP)或其他时间同步工具,确保主从服务器的系统时间保持一致。这样可以提高主从复制的可靠性,确保数据同步的正确性。
##主服务器设置##
yum install ntp -y
vim /etc/ntp.conf
--末尾添加--
server 127.127.10.0 #设置本地是时钟源,注意修改网段
fudge 127.127.10.0 stratum 8 #设置时间层级为8(限制在15内)
service ntpd start
##从服务器设置##
yum install ntp ntpdate -y
service ntpd start
/usr/sbin/ntpdate 192.168.10.15 #进行时间同步
crontab -e #设置定时任务
*/30 * * * * /usr/sbin/ntpdate 192.168.10.15
----主服务器的mysql配置-----
vim /etc/my.cnf
server-id = 11 #配置唯一id
log-bin=master-bin #添加,主服务器开启二进制日志
binlog_format = MIXED
log-slave-updates=true #添加,允许slave从master复制数据时可以写入到自己的二进制日志
systemctl restart mysqld
mysql -u root -p123456
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.41.%' IDENTIFIED BY '123456'; #给从服务器授权
FLUSH PRIVILEGES; #刷新
show master status;
//如显示以下
+-------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+-------------------+----------+--------------+------------------+
| master-bin.000001 | 603 | | |
+-------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
#File 列显示日志名,Position 列显示偏移量
----从服务器的mysql配置----
vim /etc/my.cnf
server-id = 22 #修改,注意id与Master的不同,两个Slave的id也要不同
relay-log=relay-log-bin #添加,开启中继日志,从主服务器上同步日志文件记录到本地
relay-log-index=slave-relay-bin.index #添加,定义中继日志文件的位置和名称,一般和relay-log在同一目录
relay_log_recovery = 1 #选配项
#当 slave 从库宕机后,假如 relay-log 损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的 relay-log,并且重新从 master 上获取日志,这样就保证了relay-log 的完整性。默认情况下该功能是关闭的,将 relay_log_recovery 的值设置为 1 时, 可在 slave 从库上开启该功能,建议开启。
systemctl restart mysqld
mysql -u root -p123456
CHANGE master to master_host='192.168.41.11',master_user='myslave',master_password='123456',master_log_file='master-bin.000001',master_log_pos=603;#配置同步,注意 master_log_file 和 master_log_pos 的值要与Master查询的一致
start slave; #启动同步,如有报错执行 reset slave;
show slave status\G #查看 Slave 状态
//确保 IO 和 SQL 线程都是 Yes,代表同步正常。
Slave_IO_Running: Yes #负责与主机的io通信
Slave_SQL_Running: Yes #负责自己的slave mysql进程
#一般 Slave_IO_Running: No 的可能性:
1、网络故障
2、my.cnf配置出错
3、密码、file文件名、pos偏移量不对
4、防火墙没有关闭
5、不能使用克隆服务器,uuid相同和server-id相同一样,都是唯一识别的。
----验证主从复制效果----
主服务器上进入执行 create database db_test;
去从服务器上查看 show databases;
##安装 Java 环境##
因为 Amoeba 基于是 jdk1.5 开发的,所以官方推荐使用 jdk1.5 或 1.6 版本,高版本不建议使用。
cd /opt/
cp jdk-6u14-linux-x64.bin /usr/local/
cd /usr/local/
chmod +x jdk-6u14-linux-x64.bin
./jdk-6u14-linux-x64.bin #会出现协议让你浏览,直接回车到末尾,会出现选项,输入yes,回车
mv jdk1.6.0_14/ /usr/local/jdk1.6
#配置jdk和amoeba路径
vim /etc/profile
export JAVA_HOME=/usr/local/jdk1.6
export CLASSPATH=$CLASSPATH:$JAVA_HOME/lib:$JAVA_HOME/jre/lib
export PATH=$JAVA_HOME/lib:$JAVA_HOME/jre/bin/:$PATH:$HOME/bin
export AMOEBA_HOME=/usr/local/amoeba
export PATH=$PATH:$AMOEBA_HOME/bin
#刷新配置使设置生效,并查看版本是否正确
source /etc/profile
java -version
##安装 Amoeba软件##
mkdir /usr/local/amoeba
tar zxvf amoeba-mysql-binary-2.2.0.tar.gz -C /usr/local/amoeba/
chmod -R 755 /usr/local/amoeba/
/usr/local/amoeba/bin/amoeba
#如显示amoeba start|stop说明安装成功
#先在Master、Slave1、Slave2 的mysql上开放权限给 Amoeba 访问
grant all on *.* to test@'192.168.41.%' identified by '123456';
#再回到amoeba服务器配置amoeba服务:
cd /usr/local/amoeba/conf/
cp amoeba.xml amoeba.xml.bak
vim amoeba.xml #修改amoeba配置文件
--30行--
<property name="user">amoeba</property>
--32行--
<property name="password">123456</property>
--115行--
<property name="defaultPool">master</property>
--117-去掉注释-
<property name="writePool">master</property>
<property name="readPool">slaves</property>
cp dbServers.xml dbServers.xml.bak
vim dbServers.xml #修改数据库配置文件
--23行--注释掉 作用:默认进入test库 以防mysql中没有test库时,会报错
<!-- <property name="schema">test</property> -->
--26--修改
<property name="user">test</property>
--28-30--去掉注释
<property name="password">123456</property>
--45--修改,设置主服务器的名Master
<dbServer name="master" parent="abstractServer">
--48--修改,设置主服务器的地址
<property name="ipAddress">192.168.41.31</property>
--52--修改,设置从服务器的名slave1
<dbServer name="slave1" parent="abstractServer">
--55--修改,设置从服务器1的地址
<property name="ipAddress">192.168.41.32</property>
--58--复制上面6行粘贴,设置从服务器2的名slave2和地址
<dbServer name="slave2" parent="abstractServer">
<property name="ipAddress">192.168.10.16</property>
--65行--修改
<dbServer name="slaves" virtual="true">
--71行--修改
<property name="poolNames">slave1,slave2</property>
/usr/local/amoeba/bin/amoeba start& #启动Amoeba软件,按ctrl+c 返回
netstat -anpt | grep java #查看8066端口是否开启,默认端口为TCP 8066
----测试读写分离 ----
yum install -y mariadb-server mariadb
systemctl start mariadb.service
在客户端服务器上测试:
mysql -u amoeba -p123456 -h 192.168.41.21 -P8066
//通过amoeba服务器代理访问mysql ,在通过客户端连接mysql后写入的数据只有主服务会记录,然后同步给从--从服务器
在主服务器上:
use db_test;
create table test (id int(10),name varchar(10),address varchar(20));
在两台从服务器上:
stop slave; #关闭同步
use db_test;
//在slave1上:
insert into test values('1','zhangsan','this_is_slave1');
//在slave2上:
insert into test values('2','lisi','this_is_slave2');
//在主服务器上:
insert into test values('3','wangwu','this_is_master');
//在客户端服务器上:
use db_test;
select * from test; //客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器上添加的数据,没有在主服务器上添加的数据
insert into test values('4','qianqi','this_is_client'); //只有主服务器上有此数据
//在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据
start slave;