2台阿里云服务器centOS系统下mysql进行主主同步实现以及遇到的问题

项目背景:

原有的项目是在一台服务器上运行,服务器一旦宕机,系统就无法使用。为了让系统不间断运行,至少要2台服务器集群部署,一个宕机了另一个还能运行。那么这时候就涉及到一个问题,项目部署到2台服务器上每个服务器上的数据库如何同步呢,这时候就想到主从同步了,但是主从同步是主服务器的数据进行修改后,从服务器的数据库进行更新,从服务器的数据库并不能进行修改操作。为了让2个服务器的数据库都能读写数据,就要实现主主同步。

服务器环境:

第一台服务器:阿里云centOS6.8 32位   MySQL5.1   公网IP 47.99.91.1(IP假的哈,举例而已)

第二台服务器:阿里云centOS7.8 64位   MySQL5.7   公网IP 47.99.91.2(IP假的哈,举例而已)

具体实现步骤:

步骤1:在服务器1中修改my.cnf配置

输入命令:vi /etc/my.cnf 

然后按i键进入编辑模式,在文件最后面添加以下内容:

server-id = 1       #这个是mysql的id要唯一,每个服务器上的不一样,可以从1开始 

log-bin = mysql-bin  #这个配置意思是开启二进制日志,只有开启了,别的服务器上传的mysql才能同步

binlog-do-db = mms  #这个是配置需要同步的数据库,如果有多个需要同步,多写几行

sync_binlog = 1  #这个默认为0,表示异步同步,性能好但是数据有丢失的可能性。设置为1表示同步同步,性能低但是数据不会丢失

binlog_format = mixed  #这个是为了保证主键不重复

auto-increment-increment = 2    

auto-increment-offset = 1   

slave-skip-errors = all  #跳过所有的错误,继续执行复制操作

关于以上参数的一些具体提示:

1.sync_binlog这个参数是对于MySQL系统来说是至关重要的,他不仅影响到Binlog对MySQL所带来的性能损耗,而且还影响到MySQL中数据的完整性。对于"sync_binlog"参数的各种设置的说明如下:

sync_binlog=0,当事务提交之后,MySQL不做fsync之类的磁盘同步指令刷新binlog_cache中的信息到磁盘,而让Filesystem自行决定什么时候来做同步,或者cache满了之后才同步到磁盘。

sync_binlog=n,当每进行n次事务提交之后,MySQL将进行一次fsync之类的磁盘同步指令来将binlog_cache中的数据强制写入磁盘。

在MySQL中系统默认的设置是sync_binlog=0,也就是不做任何强制性的磁盘刷新指令,这时候的性能是最好的,但是风险也是最大的。因为一旦系统Crash,在binlog_cache中的所有binlog信息都会被丢失。而当设置为“1”的时候,是最安全但是性能损耗最大的设置。因为当设置为1的时候,即使系统Crash,也最多丢失binlog_cache中未完成的一个事务,对实际数据没有任何实质性影响。

2.在做主主同步前,提醒下需要特别注意的一个问题:

主主复制和主从复制有一些区别,因为多主中都可以对服务器有写权限,所以设计到自增长重复问题,例如:

出现的问题(多主自增长ID重复)

1)首先在A和B两个库上创建test表结构;

2)停掉A,在B上对数据表test(存在自增长属性的ID字段)执行插入操作,返回插入ID为1;

3)然后停掉B,在A上对数据表test(存在自增长属性的ID字段)执行插入操作,返回的插入ID也是1;

4)然后 同时启动A,B,就会出现主键ID重复

解决方法:

只要保证两台服务器上的数据库里插入的自增长数据不同就可以了

如:A插入奇数ID,B插入偶数ID,当然如果服务器多的话,还可以自定义算法,只要不同就可以了

在下面例子中,在两台主主服务器上加入参数,以实现奇偶插入!

记住:在做主主同步时需要设置自增长的两个相关配置,如下:

auto_increment_offset     表示自增长字段从那个数开始,取值范围是1 .. 65535。这个就是序号。如果有n台mysql机器,则从第一台开始分为设1,2...n

auto_increment_increment    表示自增长字段每次递增的量,其默认值是1,取值范围是1 .. 65535。如果有n台mysql机器,这个值就设置为n。

在主主同步配置时,需要将两台服务器的:

auto_increment_increment     增长量都配置为2

auto_increment_offset        分别配置为1和2。这是序号,第一台从1开始,第二台就是2,以此类推.....

这样才可以避免两台服务器同时做更新时自增长字段的值之间发生冲突。(针对的是有自增长属性的字段)

把这些参数设置好后,按esc键退出编辑模式,输入命令  :wq  保存文件

步骤2:在服务器1中创建用于同步的账号

mysql> grant replication slave on mms.* to 'repl01'@'47.99.91.2' identified by '123456';

mysql> flush privileges;

第一句话的意思:创建并授权账号repl01拥有mms数据库的所有权限,密码为123456,只能从ip为47.99.91.2来访问

第二句话的意思是刷新权限

步骤3:在服务器2中修改my.cnf配置

输入命令:vi /etc/my.cnf 

添加的内容和第一步基本一样,就是2处不一样

server-id = 2  

auto-increment-offset = 2

步骤4:在服务器2中创建用于同步的账号

mysql> grant replication slave on mms.* to 'repl02'@'47.99.91.1' identified by '456789';

mysql> flush privileges;

第一句话的意思:创建并授权账号repl02拥有mms数据库的所有权限,密码为456789,只能从ip为47.99.91.1来访问

第二句话的意思是刷新权限

步骤5:把服务器1和服务器2的数据调整一致(如果2个服务器都是新建的这一步可省略)

在同步之前把2个服务器中数据库内的数据都自己手动复制成一样的,那么开启同步后,所有数据都一样了。我这边手动同步是用MySQL-Front这个软件远程连接了2个服务器,然后把原先运行的那个服务器中mms库里数据导出为sql文件,然后又导入到新建的那个服务器的数据库中的。这一步你们也可以用其他方式。

步骤6:在服务器1中同步服务器2

先去服务器2中mysql中输入命令  show master status; 获取2个参数

mysql> show master status;

+------------------+----------+--------------+------------------+-------------------+

| File       | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+------------------+----------+--------------+------------------+-------------------+

| mysql-bin.000001 |   256 |       |          |          |

+------------------+----------+--------------+------------------+-------------------+

1 row in set (0.00 sec)

然后在服务器1中mysql中输入以下命令

mysql> change master to master_host='47.99.91.2',master_user='repl02',master_password='456798',master_log_file='mysql-bin.000001',master_log_pos=256;

这句命令设置的意义就在于,服务器1的mysql一旦开启了同步后,就从去服务器2的ip地址根据master_log_file和master_log_pos这2个参数读取服务器2的mysql的二进制日志文件,服务器1的mysql读取到了之后就更新数据。

输入命令开启同步

mysql> start slave;

mysql> show slave status \G;

*************************** 1. row ***************************

             Slave_IO_State: Waiting for master to send event

              Master_Host: 47.99.91.1

              Master_User: repl

              Master_Port: 3306

             Connect_Retry: 60

            Master_Log_File: mysql-bin.000001

          Read_Master_Log_Pos: 158

           nelay_Log_File: mysql-relay-bin.000003

             Relay_Log_Pos: 750

        Relay_Master_Log_File: mysql-bin.000001

            Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

            ..................

只要黄色2行是yes就表示服务器1的同步成功,这时你去修改、添加、删除服务器2的mysql数据时,服务器1的也会同步了

步骤7:在服务器2中同步服务器1

先去服务器1中mysql中输入命令  show master status; 获取2个参数

mysql> show master status;

+------------------+----------+--------------+------------------+-------------------+

| File       | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |

+------------------+----------+--------------+------------------+-------------------+

| mysql-bin.000003 |   100 |       |          |          |

+------------------+----------+--------------+------------------+-------------------+

1 row in set (0.00 sec)

然后在服务器2中mysql中输入以下命令

mysql> change master to master_host='47.99.91.1',master_user='repl01',master_password='4123465',master_log_file='mysql-bin.000003',master_log_pos=100;

这句命令设置的意义就在于,服务器2的mysql一旦开启了同步后,就从去服务器1的ip地址根据master_log_file和master_log_pos这2个参数读取服务器1的mysql的二进制日志文件,服务器2的mysql读取到了之后就更新数据。

输入命令开启同步

mysql> start slave;

mysql> show slave status \G;

*************************** 1. row ***************************

             Slave_IO_State: Waiting for master to send event

              Master_Host: 47.99.91.2

              Master_User: repl

              Master_Port: 3306

             Connect_Retry: 60

            Master_Log_File: mysql-bin.000001

          Read_Master_Log_Pos: 158

           nelay_Log_File: mysql-relay-bin.000003

             Relay_Log_Pos: 750

        Relay_Master_Log_File: mysql-bin.000001

            Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

            ..................

只要黄色2行是yes就表示服务器2的同步成功,这时你去修改、添加、删除服务器1的mysql数据时,服务器2的也会同步了

这样就实现了2台服务器的数据实时同步

但是,接下来会遇到几个问题。我这边的处理办法都记录在这里

问题1:Last_IO_Error: error connecting to master error connecting to master 'copy1@59.110.138.172:3306' - retry-time: 60  retries: 2, Error_code: 1045

服务器1的slave正常,但是当我打开服务器2查询slave时,显示报错。最后检查出来是我给服务器2设置

change master to master_host='47.99.91.1',master_user='repl01',master_password='4123465',master_log_file='mysql-bin.000003',master_log_pos=100;时把IP地址写错了

这种错误一般是账号、密码、IP地址这些错误导致的

问题2:Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 'Slave can not handle replication events with the checksum that master is configured to log; the first event 'mysql-bin.000006' a'

这个问题导致的原因是我服务器2的mysql是5.1,而服务器1的mysql是5.7版本。我服务器1中没有配置一个参数binlog_checksum = none  。这个参数的意思是跳过现有的采用checksum的事件。mysql5.6.5以后的版本中binlog_checksum=crc32,而低版本都是binlog_checksum=none。也就说说我服务器2mysql是5.1的作为从数据库,那么服务器1给它传输日志内容时,也要跳过现有的采用checksum的事件,不然5.7中默认为binlog_checksum=crc32,这样传输过去,5.1不能识别,就导致上面的错误了。所以只要在服务器1中5.7的版本中设置binlog_checksum=none就能解决。

输入命令  vi /etc/my.cnf 

然后在文件内添加参数  binlog_checksum=none,再保存一下,之后再重启一下mysql5.7

问题3:Last_SQL_Error: Relay log read failure: Could not parse relay log event entry. The possible reasons are: the master's binary log is corrupted (you can check this by running 'mysqlbinlog' on the binary log), the slave's relay log is corrupted (you can check this by running 'mysqlbinlog' on the relay log), a network problem, or a bug in the master's or slave's MySQL code. If you want to check the master's binary log or slave's relay log, you will be able to know their names by issuing 'SHOW SLAVE STATUS' on this slave.

前面2个问题都解决了,我以为就OK了,谁知我太天真。前面问题都解决后,2个服务器mysql中输入show slave status \G命令后,都显示同步正常了,也不报错了。我先修改了服务器2中mysql5.1的数据,服务器1中mysql5.7里数据的确是同步了。但是当我在服务器1中mysql5.7中修改数据时,服务器2中mysql5.1进入后用show slave status \G命令查看同步情况,就发现报上面的错误。。。。我各种百度,各种方法试过都没法解决。最后看到有一篇文章说做主从同步的mysql最好要版本一致,至少是版本号的前2位要一致,比如5.7.xx1和5.7.xx2。无奈之下,我重新安装了服务器2中的mysql,从5.1升级到5.7。升级过程中也遇到些问题,不过都百度解决了。升级完成后,再做配置一次同步。最后就实现了主主同步。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值