Windows与Linux上MySql数据库主从同步
原理
众所周知,主从同步有两种数据库类型:master、slave。
master会将自己所经历的一切动作都记录在binlog(二进制文件中),而slave拿到这个文件就会产生自己的relay log(中继日志),slave再根据中继日志进行执行。
话说完成一次同步将会用到三个线程:binlog dump线程、i/o线程、sql线程;其中binlog dump线程为master所有,i/o线程、sql线程则为slave所有。
首先主库创建binlog dump线程,目的是观察并记录master的动作,接着master将信息异步传达给i/o线程;之后slave则需要产生i/o线程来与主库进行连接,目的是获取binlog信息;最后i/o线程将根据binlog文件创造出中继日志,slave的sql线程根据中继日志执行更新产生与主库相同的数据。而relay log在用过一次后就被会被清除,这样可以减少对磁盘的占有。
master与slave之间对应关系
它们之间有几种对应关系呢?
单master——单slave
单master——单master
单master——多并slave
多串master——多并slave
这些对应关系会应用到具体的工作环境中。
mysql数据库版本
这里准备在Windows和Linux虚拟机各自的mysql数据库之间建立主从同步关系。Windows上mysql为主库,Linux上mysql为从库,使其之间能异步的传递数据。
需要的两个mysql数据库准备好了,版本信息如下:
windows:mysql-5.5.48-winx64.zip
Linux:MySQL-server-5.5.48-1.linux2.6.x86_64.rpm、MySQL-client-5.5.48-1.linux2.6.x86_64.rpm
二者之间版本需要尽量接近,最好一致。
确保主从彼此连接
windows与linux的数据库需要建立连接所以需要彼此ping通,首先关闭各自的防火墙
linux关闭防火墙命令:
service iptabes stop
接着查看各自的ip地址
windows——ipconfig
linux——ifconfig
linux ping ipv4地址:
ping 192.168.43.61
windows ping inet地址:
ping 192.168.159.31
各自的配置文件信息
windows——my.ini
[mysql] 注:蓝色为开启主从同步的必要条件,其它有关主从配置的属性不配也可以。 |
server-id,无论master还是slave,server-id只能有一个,且不能相同。
log-bin,会保存binlog二进制文件,只要它被配置进去就会开始记录。
需要注意的是mysql_log_bin和log-err这两个文件夹的位置必须直接在data文件夹下,否则mysql服务无法启动。
如果写成这样:log-err=C:Program Files (x86)mysql-5.5.48-winx64datalogmysql_log_err 服务器就无发正常启动。
binlog-do-db、binlog-ignore-db两个属性不进行设置的话,master默认会对未来所有的数据库进行记录binlog。不过在主从同步机制开启之前的旧数据并不会被slave同步,因为binlog没有其对应记录。所以说,如果之前master里已经有数据,而又想被slave同步可以有几种解决方法。其中一个方法比较繁琐:是先屏蔽写锁,然后对旧数据进行备份>>再删除旧数据>>最后打开被屏蔽的写锁、恢复旧数据,恢复旧数据的动作就会被记录,并同步到slave中;另一个方法比较简单:是通过mysqldump导出master数据,然后复制全部的备份的文件到从数据库即可。
read-only有两种状态:0代表可读可写,1代表只读。
配置并保存,接着cmd以管理员身份重启windows上mysql服务(或者直接在计算机管理>服务——找到mysq服务启动就可以了)。
下面用命令控制mysql服务重启:
net stop mysql
net start mysql
linux——my.cnf
由于我的/etc下没有my.cnf文件所以需要去/usr/share/mysql/my-medium.cnf复制一份到/etc,取名为my.cnf即可,二者不会冲突。
# Example MySQL config file for medium systems. # # This is for a system with little memory (32M - 64M) where MySQL plays # an important part, or systems up to 128M where MySQL is used together with # other programs (such as a web server) # # MySQL programs look for option files in a set of # locations which depend on the deployment platform. # You can copy this option file to one of those # locations. For information about these locations, see: # http://dev.mysql.com/doc/mysql/en/option-files.html # # In this file, you can use all long options that a program supports. # If you want to know which options a program supports, run the program # with the "--help" option. # The following options will be passed to all MySQL clients [client] #password = your_password port = 3306 socket = /var/lib/mysql/mysql.sock # Here follows entries for some specific programs # The MySQL server [mysqld] port = 3306 socket = /var/lib/mysql/mysql.sock skip-external-locking key_buffer_size = 16M max_allowed_packet = 1M table_open_cache = 64 sort_buffer_size = 512K net_buffer_length = 8K read_buffer_size = 256K read_rnd_buffer_size = 512K myisam_sort_buffer_size = 8M # Don't listen on a TCP/IP port at all. This can be a security enhancement, # if all processes that need to connect to mysqld run on the same host. # All interaction with mysqld must be made via Unix sockets or named pipes. # Note that using this option without enabling named pipes on Windows # (via the "enable-named-pipe" option) will render mysqld useless! # #skip-networking # Replication Master Server (default) # binary logging is required for replication log-bin=mysql-bin # binary logging format - mixed recommended binlog_format=mixed # required unique id between 1 and 2^32 - 1 # defaults to 1 if master-host is not set # but will not function as a master if omitted #server-id = 1 # Replication Slave (comment out master section to use this) # # To configure this host as a replication slave, you can choose between # two methods : # # 1) Use the CHANGE MASTER TO command (fully described in our manual) - # the syntax is: # # CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>, # MASTER_USER=<user>, MASTER_PASSWORD=<password> ; # # where you replace <host>, <user>, <password> by quoted strings and # <port> by the master's port number (3306 by default). # # Example: # # CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306, # MASTER_USER='joe', MASTER_PASSWORD='secret'; # # OR # # 2) Set the variables below. However, in case you choose this method, then # start replication for the first time (even unsuccessfully, for example # if you mistyped the password in master-password and the slave fails to # connect), the slave will create a master.info file, and any later # change in this file to the variables' values below will be ignored and # overridden by the content of the master.info file, unless you shutdown # the slave server, delete master.info and restart the slaver server. # For that reason, you may want to leave the lines below untouched # (commented) and instead use CHANGE MASTER TO (see above) # # required unique id between 2 and 2^32 - 1 # (and different from the master) # defaults to 2 if master-host is set # but will not function as a slave if omitted server-id = 2 # # The replication master for this slave - required #master-host = <hostname> # # The username the slave will use for authentication when connecting # to the master - required #master-user = <username> # # The password the slave will authenticate with when connecting to # the master - required #master-password = <password> # # The port the master is listening on. # optional - defaults to 3306 #master-port = <port> # # binary logging - not required for slaves, but recommended #log-bin=mysql-bin # Uncomment the following if you are using InnoDB tables #innodb_data_home_dir = /var/lib/mysql #innodb_data_file_path = ibdata1:10M:autoextend #innodb_log_group_home_dir = /var/lib/mysql # You can set .._buffer_pool_size up to 50 - 80 % # of RAM but beware of setting memory usage too high #innodb_buffer_pool_size = 16M #innodb_additional_mem_pool_size = 2M # Set .._log_file_size to 25 % of buffer pool size #innodb_log_file_size = 5M #innodb_log_buffer_size = 8M #innodb_flush_log_at_trx_commit = 1 #innodb_lock_wait_timeout = 50 [mysqldump] quick max_allowed_packet = 16M [mysql] no-auto-rehash # Remove the next comment character if you are not familiar with SQL #safe-updates [myisamchk] key_buffer_size = 20M sort_buffer_size = 20M read_buffer = 2M write_buffer = 2M [mysqlhotcopy] interactive-timeout 注:蓝色为需要改动部分,该文件默认开启了binlog功能。其它属性就无需改动了。 |
保存更改,接着需要重启linux上mysql服务:
service mysql restart
windows上master授权给slave
首先windows上cmd登陆mysql:
mysql -hlocalhost -uroot -p
接着键入授权命令:
用户授权(给自身授权,必须执行,否则slave的io线程可能连接不上,并处于"Connecting"状态)
grant all privileges on *.* to 'root'@'%' identified by '' with grant option;
给slave用户授权,使它拥有权力复制
grant replication slave on *.* to 'root'@'192.168.159.31' identified by ' ' ;
'root'是数据库用户名。
‘192.168.159.31’是ens33里的inet。
‘ ’是数据库密码(我没有设置数据库密码);
之后命令刷新一下:
flush privileges;
查看当前master的状态
show master status
可以看到4个字段
File就是已经生成的binlog,在my.ini配置文件中可以自定义binlog文件名,所以我的文件名是mysql_log_bin.000003,因此说我们有对这个binlog文件的命名权力。
可以看到data文件夹中生成的文件:
position是slave当前读取文件的位置,称为”偏移量“会一直发生变动,即slave会从这个点进行数据同步。
binlog_do_db、binlog_ignore_db由于没有进行配置所以里面不会有数据库名称列表。
如果你没有在my.ini中配置主从同步信息的话,在你键入“show master status“后会显示:“Empty set”。
在linux的mysql中指定master信息
首先在控制台登陆到linux上的mysql
mysql -uroot -p
[root@localhost etc]# mysql -uroot -p Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. Oracle is a registered trademark of Oracle Corporation and/or its Type 'help;' or 'h' for help. Type 'c' to clear the current input statement. mysql> |
接着为slave指定master信息
change master to master_host='192.168.43.61',
master_user='root',
master_password='',
master_log_file='mysql_log_bin.000003' ,
master_log_pos=331;
mysql> change master to master_host='192.168.43.61',master_user='root',master_password='', |
同时给mysql的root用户授权(一定要授权,否则,io线程可能连接不上)
grant all privileges on *.* to 'root'@'%' identified by '' with grant option;
mysql> grant all privileges on *.* to 'root'@'%' identified by '' with grant option; |
我的mysql数据库也是没有设置密码,请针对自身密码进行设置。
启动slave
start slave;
mysql> start slave; |
显示slave的状态
show slave status;(稍有点乱)
mysql> show slave status; mysql> |
或者
show slave statusG;
mysql> show slave statusG; ERROR: mysql> |
可以看到橙色部分的io线程状态不为Yes,而是connecting,并且有错误的日志生成,所以处于异常状态。因为master的Exec_Master_Log_Pos已经不再是331了(中途我操作了master数据库),导致pos改变。
这是其中一点原因,还有一点是我之前没有对各自的数据库用户赋予所有权限:grant all privileges on *.* to 'root'@'%' identified by '' with grant option;
所以说:Slave_IO_Running 和 Slave_SQL_Running都必须为Yes才是正确的状态,否则就是有问题。
引起不为Yes的原因主要有:
1 两个数据库的权限不足
2 指定的master或slave的个别参数错误,如:用户名或密码不正确、master_log_pos参数不匹配
3 网络有问题
所以在排除以上因素后我按照原有顺序重新执行了一遍:
windows中:
可以看到position已经变化为1756,因此需要重新在slave中对master进行指定参数。
linux中:
mysql> change master to master_host='192.168.43.61',master_user='root',master_password='', master_log_file='mysql_log_bin.000003',master_log_pos=1756; mysql> change master to master_host='192.168.43.61',master_user='root',master_password='', master_log_file='mysql_log_bin.000003',master_log_pos=1756; mysql> start slave; |
接着
show slave statusG;
mysql> show slave statusG; ERROR: mysql> |
这就是正确的方式,至此主从同步就实现了。
测试
可以用navacat来测试一下,这里是windows上navicat,现在在master上新建立一个数据库”db0325“,使用该数据库,并在db0325中新建一个表”test“,之后向test表插入信息并查询。
mysql> create database db0325;(数据库命名不能有下划线_) --新建数据库 Query OK, 1 row affected
mysql> use db0325; --使用当前数据库
Database changed
mysql> create table test( --新建表 stuname varchar(20) primary key, stusex char(3), stuage int(10), birthday datetime not null ); Query OK, 0 rows affected
mysql> insert into test (stuname,stusex,stuage,birthday) values ('张三','男',36,('1985-2-25,00:00:01')); --插入语句 Query OK, 1 row affected
mysql> select * from test; --查询 +---------+--------+--------+---------------------+ | stuname | stusex | stuage | birthday | +---------+--------+--------+---------------------+ | 张三 | 男 | 36 | 1985-02-25 00:00:01 | +---------+--------+--------+---------------------+ 1 row in set
mysql>
来到linux
看slave是否和刚才的信息同步。
mysql -uroot -p
show databases;
可以看到除了自带的数据库以外,多了一个db0325。
use db0325;
select * from test;
测试没有出现问题,主从同步成功。
从结果可以验证;slave的确只能从得到binlog的时候同步数据,而之前的数据就要通过mysqldump备份的方式导入到slave中。
好啦,看到这里如果你也想配置MySQL数据库间的主从同步,就赶快动手配置一下吧,如果您有更加新奇的知识点,欢迎补充,如有不足之处还请赐教>>>