主从、主备: mysql一个主,一个从
主主: mysql互为主从
服务器 | mysql |
---|---|
192.168.0.1 | 主 |
192.168.0.2 | 从 |
log_bin = mysql-bin
开启二进制日志,主库必须开启,可修改
server_id = 1
设置server-id,唯一值,标识主机,必须与从库不一致,可修改
binlog_format = row
mysql主从复制有三种方式:
基于SQL语句的复制(statement-based replication, SBR),基于行的复制(row-based replication, RBR),混合模式复制(mixed-based replication, MBR)。对应的,binlog的格式也有三种:STATEMENT,ROW,MIXED。
每一条会修改数据的sql语句会记录到binlog中。优点是并不需要记录每一条sql语句 和每一行的数据变化,减少了binlog日志量,节约IO,提高性能。缺点是在某些情况下会导致master-slave中的数据不一致(如sleep()函数, last_insert_id(),以及user-defined functions(udf)等会出现问题)
不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了,修改成什么样了。而且不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。缺点是会产生大量的日志,尤其是alter table的时候会让日志暴涨。
以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。
relay_log = /usr/local/mysql/log/mysql-relay-bin
relay_log_recovery=ON
定义relay_log的位置和名称,如果值为空,则默认位置在数据文件的目录(datadir),文件名为host_name-relay-bin.nnnnnn
当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为 1(ON)时,可在slave从库上开启该功能,建议开启。
同relay_log,定义relay_log的位置和名称,一般和relay-log在同一目录
设置relay-log.info的位置和名称(relay-log.info记录MASTER的binary_log的恢复位置和relay_log的位置)
是否自动清空不再需要中继日志时。默认值为1(启用)
这个参数和sync_binlog是一样的,当设置为1时,slave的I/O线程每次接收到master发送过来的binlog日志都要写入系统缓冲区,然后刷入relay log中继日志里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量I/O。
这个参数和sync_relay_log参数一样,当设置为1时,slave的I/O线程每次接收到master发送过来的binlog日志都要写入系统缓冲区,然后刷入relay-log.info里,这样是最安全的,因为在崩溃的时候,你最多会丢失一个事务,但会造成磁盘的大量I/O。当设置为0时,并不是马上就刷入relay-log.info里,而是由操作系统决定何时来写入,虽然安全性降低了,但减少了大量的磁盘I/O操作。这个值默认是0,可动态修改,建议采用默认值。
log_slave_updates = 1
使用Mysql的replication机制实现主从同步时,其是由三个线程实现了,主库一个I/O线程,从库一个I/O线程和一个SQL线程。配置时主库需要开始bin-log参数,即在配置文件中添加log-bin = /data/3307/mysql-bin该行,但是当我们需要实现级联同步时,即以这样的一个模式,A>B>C实现三级同步时,AB库除了需要设置log-bin参数还需要添加一个参数:log-slave-updates。
log-slave-updates参数默认时关闭的状态,如果不手动设置,那么bin-log只会记录直接在该库上执行的SQL语句,由replication机制的SQL线程读取relay-log而执行的SQL语句并不会记录到bin-log,那么就无法实现三级级联同步。
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
mysql 复制分为:异步复制、半同步复制、全同步复制
默认是异步复制,全同步复制和半同步复制区别就是主机接收多少个成功同步的返回,就是备机的成功个数,上边配置的的个数是1
异步复制(Asynchronous replication)
逻辑上
MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从库上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。
技术
主库将事务 Binlog 事件写入到 Binlog 文件中,此时主库只会通知一下 Dump 线程发送这些新的 Binlog,然后主库就会继续处理提交操作,而此时不会保证这些 Binlog 传到任何一个从库节点上。
原理
(1) 在Slave 服务器上执行sart slave命令开启主从复制开关,开始进行主从复制。
(2) 此时,Slave服务器的IO线程会通过在master上已经授权的复制用户权限请求连接master服务器,并请求从执行binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容
(3) Master服务器接收到来自Slave服务器的IO线程的请求后,其上负责复制的IO线程会根据Slave服务器的IO线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的IO线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的IO线程。返回的信息中除了binlog中的下一个指定更新位置。
(4) 当Slave服务器的IO线程获取到Master服务器上IO线程发送的日志内容、日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(Mysql-relay-bin.xxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取master端新binlog日志时能告诉Master服务器从新binlog日志的指定文件及位置开始读取新的binlog日志内容
(5) Slave服务器端的SQL线程会实时检测本地Relay Log 中IO线程新增的日志内容,然后及时把Relay LOG 文件中的内容解析成sql语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这样sql语句,并在relay-log.info中记录当前应用中继日志的文件名和位置点
全同步复制(Fully synchronous replication)
逻辑:
指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。
技术:
当主库提交事务之后,所有的从库节点必须收到、APPLY并且提交这些事务,然后主库线程才能继续做后续操作。但缺点是,主库完成一个事务的时间会被拉长,性能降低。
半同步复制(Semisynchronous replication)
逻辑:
是介于全同步复制与全异步复制之间的一种,主库只需要等待至少一个从库节点收到并且 Flush Binlog 到 Relay Log 文件即可,主库不需要等待所有从库给主库反馈。同时,这里只是一个收到的反馈,而不是已经完全完成并且提交的反馈,如此,节省了很多时间。
技术:
介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。
原理:
master将每个事务写入binlog(sync_binlog=1),传递到slave刷新到磁盘(sync_relay=1),同时主库提交事务(commit)。master等待slave反馈收到relay log,只有收到ACK后master才将commit OK结果反馈给客户端。
read_only=1
0: 读写都行(主库)
1: 只读(从库)
auto-increment-increment = 2
auto-increment-offset = 2
mysql中有自增长字段,在做数据库的主主同步时需要设置自增长的两个相关配置:auto_increment_offset和auto_increment_increment。
auto_increment_offset:表示自增长字段从那个数开始,他的取值范围是1 … 65535
auto_increment_increment:表示自增长字段每次递增的量,其默认值是1,取值范围是1 … 65535
在主主同步配置时,需要将两台服务器的auto_increment_increment增长量都配置为2,而要把auto_increment_offset分别配置为1和2.
plugin-load ="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
MySQL的半同步是通过加载google为MySQL提供的半同步插件 semisync_master.so 和 semisync_slave.so 来实现的。其中前者是master上需要安装的插件,后者是slave上需要安装的插件。
MySQL的插件位置默认存放在$basedir/lib/plugin目录下。例如,yum安装的mysql-server,插件目录/usr/lib64/mysql/plugin
因为要加载插件,所以应该保证需要加载插件的MySQL的全局变量 have_dynamic_loading 已经设置为YES(默认值就是YES),否则无法动态加载插件。
mysql> select @@global.have_dynamic_loading;
+-------------------------------+
| @@global.have_dynamic_loading |
+-------------------------------+
| YES |
+-------------------------------+
1 row in set (0.00 sec)
mysql 中有两种插件安装方式
命令行安装
mysql> install plugin rpl_semi_sync_master soname 'semisync_master.so';
配置文件中加载插件的方式为:
多个插件逗号分隔
[mysqld]
plugin-load="plugin_name=shared_library_name"
查看插件
mysql> show plugins;
log_bin = mysql-bin
server_id = 1
binlog_format = row
relay_log = /usr/local/mysql/log/mysql-relay-bin
relay_log_recovery=ON
log_slave_updates = 1
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
# read_only=1
# auto-increment-increment = 2
# auto-increment-offset = 2plugin-load ="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
log_bin = mysql-bin
server_id = 2
binlog_format = row
relay_log = /usr/local/mysql/log/mysql-relay-bin
relay_log_recovery=ON
log_slave_updates = 1
loose_rpl_semi_sync_master_enabled = 1
loose_rpl_semi_sync_slave_enabled = 1
# read_only=1
# auto-increment-increment = 2
# auto-increment-offset = 1plugin-load ="rpl_semi_sync_master=semisync_master.so;rpl_semi_sync_slave=semisync_slave.so"
启动两台机器的mysql,同步两台机器的数据。主从数据库需要在初始化时数据保持一致,需要导出主mysql的数据,在从mysql导入。
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%' IDENTIFIED BY '123456';mysql> show master status;
+------------------+-----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+-----------+--------------+------------------+-------------------+
| mysql-bin.000016 | 308492722 | | | |
+------------------+-----------+--------------+------------------+-------------------+
1 row in set (0.19 sec)
Slave_IO_Running、Slave_SQL_Running为yes就是同步成功了
mysql> reset slave;mysql> CHANGE MASTER TO MASTER_HOST='主数据ip',-> MASTER_PORT=3306,-> MASTER_USER='repl',-> MASTER_PASSWORD='123456',-> MASTER_LOG_FILE='mysql-bin.000016',-> MASTER_LOG_POS=308492722;mysql> show slave status\G
*************************** 1. row ***************************Slave_IO_State: Waiting for master to send eventMaster_Host: 20.206.6.28Master_User: replMaster_Port: 13306Connect_Retry: 60Master_Log_File: mysql-bin.000030Read_Master_Log_Pos: 35647810Relay_Log_File: mysql-relay-bin.000002Relay_Log_Pos: 320Relay_Master_Log_File: mysql-bin.000030Slave_IO_Running: YesSlave_SQL_Running: YesReplicate_Do_DB: Replicate_Ignore_DB: Replicate_Do_Table: Replicate_Ignore_Table: Replicate_Wild_Do_Table: Replicate_Wild_Ignore_Table: Last_Errno: 0Last_Error: Skip_Counter: 0Exec_Master_Log_Pos: 35647810Relay_Log_Space: 527Until_Condition: NoneUntil_Log_File: Until_Log_Pos: 0Master_SSL_Allowed: NoMaster_SSL_CA_File: Master_SSL_CA_Path: Master_SSL_Cert: Master_SSL_Cipher: Master_SSL_Key: Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: NoLast_IO_Errno: 0Last_IO_Error: Last_SQL_Errno: 0Last_SQL_Error: Replicate_Ignore_Server_Ids: Master_Server_Id: 103306Master_UUID: fd4f82db-be47-11ed-bb4b-327c86c2e14eMaster_Info_File: /usr/local/mysql/data/master.infoSQL_Delay: 0SQL_Remaining_Delay: NULLSlave_SQL_Running_State: Slave has read all relay log; waiting for more updatesMaster_Retry_Count: 86400Master_Bind: Last_IO_Error_Timestamp: Last_SQL_Error_Timestamp: Master_SSL_Crl: Master_SSL_Crlpath: Retrieved_Gtid_Set: Executed_Gtid_Set: Auto_Position: 0Replicate_Rewrite_DB: Channel_Name: Master_TLS_Version:
1 row in set (0.01 sec)
mysql> stop slave;mysql> reset slave;mysql> CHANGE MASTER TO MASTER_HOST='主数据ip',-> MASTER_PORT=3306,-> MASTER_USER='repl',-> MASTER_PASSWORD='123456',-> MASTER_LOG_FILE='mysql-bin.**',-> MASTER_LOG_POS=**;mysql> start slave;mysql> show slave status\G
上一篇:DNS域名解析