mysql主从复制搭建
开篇
在上家公司中,整个系统架构还是比较简单的,访问量也不是很高,单机数据库还是可以维持系统的可用性和一定性能的,而最近入职的这家虽然说公司规模不大,但是系统使用的用户数是蛮多的而且数据处理也是比上家公司复杂了很多,数据库数据量也是蛮大的,刚入职不久就看到了他们的架构图上写了个数据库的主从模式和读写分离来分担单机访问,就问了项目组的同事这些是怎么做的?他们也只是给讲了个大概,我觉得还是自己动手来操作搭建一次数据库主从模式吧。
主从复制的好处?为什么要用主从复制?
当系统访问量大时,单数据库可能无法保证系统的性能,需要配置多台数据库来提高系统性能进行读写分离,把访问量分担,同时主从复制也起到了一个数据备份的功能。
mysql主从复制的原理是什么?
- master将改变记录到二进制日志(binary log)这个过程叫做二进制日志时间 binary log events,
- slave 将binary log events 拷贝到它的中继日志(relay_log)。
- slave重做中继日志中的事件,将改变应用到自己的数据库中,mysql复制时异步的且串行化的
简单通俗说,主机把改变操作记录保存到一个日志文件中,从机获取到这个日志文件,在自己的机器上运行
mysql主从复制,一主一从的配置过程环境准备
准备两台装有mysql数据库的机器,在此笔者使用了两台虚拟机系统是ubuntu18.04,在一台机器安装好mysql数据库之后克隆就行了(通过这种方法会有一个坑后面再说),保证这两台虚拟机可上网可以相互ping通
mysql主从复制,一主一从主机配置
修改数据库配置文件 /etc/mysql/mysql.conf.d/mysqld.cnf, 注意:这个文件根据安装mysql方式不同路径不同,需要找到自己mysql的配置文件 在[mysqld]节点中配置如下:
配置说明:
- server-id:指定master服务id,必须
- log-bin=mysql-bin:需要打开日志文件,必须,这里有些人会指定一个目录,但是笔者指定一个目录之后发现mysql就启动不起来了,这里直接设置为 mysql-bin 就可以,生成的文件过后是可以使用命令查看的
- 错误日志文件归集路径,可选
- read-only=0 数据库读写模式 因为主机一般都是可读可写的,也可以使用默认值这项可选, 0为可读可写,1为只读
- binlog_do_db :这项可选所以没有配置,意思 要复制哪些数据库
- binlog_ignore_db 这项可选所以没有配置,意思 忽略复制哪些数据库
这里就完成了主机数据库配置文件的修改,保存之后重启mysql服务。
mysql主从复制,一主一从从机配置
从机数据库配置相对简单点,也是修改数据库配置文件(如上路径),只需要在【mysqld】节点中配置server-id即可:
!!!server-id不能和主机重复了,read-only这里理论上从机只做读操作,所以设置为1,但是这里有坑下文再说
从机的配置配置一个server-id就可以了保存退出,重启服务,这里我们就配置好了一台主机和从机 主机:192.168.192.133 从机:192.168.192.132
查看log-bin文件的生成位置
- 首先登录到数据库中 mysql -u root -p 根据提示输入密码
- 输入命令:show variables like '%log_bin%';
在图中我们可以看到log_bin 的value是ON说明是打开了二进制文件配置,log_bin_basenaem 的value 就是文件的保存地址,去到目录查看
!!!这里的mysql-bin.000001就是生成的二进制文件了
主机给从机链接授权
- mysql -u root -p 根据提示输入密码
- 使用命令:
grant REPLICATION SLAVE ON *.* to 'ayou'@'192.168.192.132' identified by '123456';
- 命令解析
- grant: 是数据库的授权命令
- ayou:被授权的账号
- REPLICATION SLAVE:复制权限
- '192.168.192.132':被授权登录的从机ip
- '123456':被授权账号的密码
执行命令后,再执行刷新权限表命令:
FLUSH PRIVILEGES;
查看某个账号被分配权限的命令:如
show grants for 'ayou'@'192.168.192.132'
使用命令查看master状态
show master status;
- file:二进制文件,从机要复制主机的哪一个二进制文件
- position:磁道,就是从机要从哪一个节点开始复制主机的内容
- binlog_Do_DB:要复制的哪一个数据库(这一项可在上文配置文件配置)
- Binlog_Igore_DB:要排斥复制的哪个数据库,(这一项可在上文配置文件配置)
从机连接主机配置
在上文中在主机中为从机账号授权了,现在要通过这个账号来连接主机,步骤如下:
- 登录数据库mysql -u root -p
- 登录成功后输入命令:
change master to master_host='192.168.192.133',master_user='ayou',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=10756;
命令详解:
- master_host:主机ip地址
- master_user:master授权账号
- master_password:master授权的密码
- master_log_file:对应的二进制文件,如上图所示的FIle
- master_log_pos=:对应的是master上的磁道(通俗将就是你要从二进制文件的哪个地方开始做复制)
- 输入成功后执行如下命令启动slave,:
start slave;
- 执行如下命令查看slave状态:
show slave status\G;
- slave_Io_State:状态必须显示为 Waiting for master to send event
- Slave_IO_Running:YES 状态必须显示为 YES
- Slave_SQL_Running:YES 状态必须显示为 YES
!!!以上三项条件必须满足才证明主从之间的通道打开
在搭建过程中出现的错误1
- 在搭建过程中出现,Slave_IO_Running:NO
如上图所示当我们执行从机连接主机命令且开启slave后,输入命令 show slave status\G; 时 Slave_IO_State状态为空,Slave_IO_State为NO,还有上图第三点错误,这个错误说的是从机数据库和主机数据的的UUID相等,所以直接导致了这个错误
原因:笔者在创建主从数据库时,是通过主机克隆出从机,所以数据库服务的uuid就相等了,
解决办法:
- 从机先停掉 slave
- 停掉数据库
- 删除 /var/lib/mysql/auto.cnf,这个文件就是包含了uuid的配置,启动数据库服务的时候这个文件会自动生成
- 从机再次数据命令连接主机,和启动slave
更新主机数据库,在从机看是否同步成功
如上所示我们在主机数据库创建了test数据库,在test数据库中创建了test数据表,在表中插入了一条记录,按理说主从连接通道已经建立好此时去从机查看就会和主机数据一致,我们查看从机数据库
再试一次,在主机上插入数据
insert into test values(1,'234789');
返回从机查看,
发现数据同步是成功的!!!!,说明我们的主从复制是生效的!!!!
这里补充一下,如果在生产过程中,你的从库是后面再搭建的而主库已经有一些数据库表和数据了, 从库数据的复制是从主从架构搭建之后的,所以搭建之前的主库的数据需要手动导入到从库后建立主从复制机制。
主从数据库数据不一致的如何解决?
数据库出现不一致时从机的slave状态 出现Slave_SQL_Running: No
解决方法1(忽略错误,继续同步):
- 从机stop slave;
- 输入命令 set global sql_slave_skip_counter=1;
- 从机 start slave
该方法适用于主从库数据相差不大,或者要求数据可以不完全统一的情况,数据要求不严格的情况
解决方法2(重新做主从复制,完全同步):
- 从机stop slave
- 主机给表加上读锁,因为要做备份所以备份期间不允许其他人增,删数据
flush table with read lock;
- 把主机数据库备份(mysqldump 命令不需要登录数据库,直接在虚拟机目录执行就可以) 备份某个数据库命令:
mysqldump -uroot -p test > /etc/mysql/back/test.sql
例子:备份test 库 test3 和test4 两张表,多表使用空格间隔
mysqldump -uroot -p test test4 test3 > /etc/mysql/back/test34.sql
命令解释:
- mysqldump:数据库备份命令
- -uroot:指定数据库账户
- -p:数据库密码,执行命令后会请求输入密码
- test:数据库名称
- /etc/mysql/back/test.sql :备份出来的sql文件存放路径
4.把从主机备份的sql脚本上传至从机,并执行命令
注意:如果备份到一个全新的从库中,没有相对应的数据库是需要先执行创建数据库的命令,可登录数据库通过命令
create database db_name
或者通过备份命令:
mysqladmin -uroot -p create db_name
确保数据库存在之后再执行备份命令如下:
mysql -uroot -p test< /home/ayou/test.sql
- "<" 右边就是存放备份脚本的路径
- 查看主机二进制文件名和position数值,
- 从机重新连接主机,
change master to master_host='192.168.192.133',master_user='ayou',master_password='123456',master_log_file='mysql-bin.000003',master_log_pos=1796;
- 重新启动slave输入命令:start slave,输入命令: show slave status\G; 如下图显示说明操作成功
8 对主机数据库解锁:
unlock tables;
这一步必须执行的哦不要忘记了!!!!!!!!!!
要把主数据库和从数据库的责任分担明确
上文操作中我们已经把主从复制搭建好了,但是“主从复制”这四个字常常伴随着“读写分离”四个字,在开发中我们为了避免主从数据库数据冲突,需要给主数据库可读可写的权限,从数据库拥有读的权限就可。写数据的时候都往主数据库写,而读数据时则可以通过java活其他程序来规定读取哪个数据库。
从数据库创建普通账户和授权
- 创建用户 luo
- create user
luo@*identified by'123456'; - 给用户授权为 只用于 select权限
grant select ON *.* to `luo`@`*` identified by'123456';
使用此账号登录从数据库
- mysql -u luo -p
- 根据提示输入密码
- 在从库上删除一条数据
当我们之心DML语句是就会报以下错误:
ERROR 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
报错中有一个单词 “read-only”,这个正是我们在上文数据库配置文件中配置为1的,如果在上文我们忽略这个配置,这里的报错就会变成 Access denied(权限不足)类型的错误。
!!!但是从库有全部权限的用户还是可以对数据进行DML操作的,全部权限是指 拥有 all privileges 的账户
最后有一个疑问
主从复制中从库的DML难道要靠角色权限来控制吗?能不能在master给从库授权连接账号时指定只读权限? 既然都说从数据库只需要读的权限了,那我们在主机给从机授权时是不是只要修改命令为如下命令就可?
grant select ON *.* to 'ayou'@'192.168.192.132' identified by '123456';
但是很不幸的是,当把授权命令改为以上命令后,slave是连接不上master的,就无法配置主从复制了,配置后如下图错误
最后的话:
本篇日记是笔者学习主从复制的笔记,总结的可能不是很好但也回答了 什么是主从复制?使用场景?有什么优势? 怎么搭建? 数据不一致怎么办? 数据库层面的读写分离配置 这几个问题,最后的疑问如有大佬指点,感激不尽。好! 就这样!exit bye