MySQL主从复制以及读写分离
一. 原理篇
1. 主从复制原理
1.1 支持的复制类型
(1) 基于语句复制:在主服务器上执行的sql语句,在从服务器上执行同样的语句。
(2) 基于行的复制:把改变的内容复制过去,而不是在从服务器上在执行一遍。
(3) 混合复制类型:默认采用基于语句的复制,一旦发现基于语句无法精确复制时,就会采用基于行的复制。
1.2 复制的工作过程
(1) 在每个事务更新完成时,master会在二进制日志记录这些改变。写入二进制日志完成后,master通知存储引擎提交事务。
(2) Slave将Master的Binary log复制到其中继日志,Slave打开一个I/O工作线程,I/O线程在Master上打开一个网络连接,然后Binlog dump process从Master的二进制日志中读取事件,如果已经成功链接到Master,则会进行睡眠并等待Master产生新的事件。I/O线程将这些事件写入中继日志。
(3) SQL slave thread(SQL 从线程)处理该过程的最后一步。SQL线程从中继日志读取事件,并重放其中的事件而更新Slave的数据,使其与Master中的数据一致,只要该线程与I/O线程保持一致,中继日志通常会位于OS的缓存中,所以中继日志开销很小。
以上就是mysql主从复制的原理,Slave可以有多台,主服务也可以有多台,可以使用keepalived做HA的高可用性,建议mysql的数据不要只放在共享存储上,而是每个Slave都拥有一个单独的存储存放数据。
复制的过程中有一个很重要的限制,即复制在Slave上是串行化的,也就是说Master上的并行更新操作不能在Slave上并行操作,也就是不能同时执行。
2. 读写分离原理
实现读与写的分离,就是在从服务器上读取数据,在主服务器上写入数据。
读写分离要建立在主从复制的基础上,基本原理就是让主服务器处理事务性增、改、删(insert、update、delete)操作,而从服务器处理select查询。
数据库复制被用来把事务性操作导致的变更同步到集群中的从数据库。
目前较为常见的Mysql读写分离分为两种:
基于程序代码内部实现:在代码中根据select 、insert进行路由分类,这类方法也是目前生产环境下应用最广泛的。优点是性能较好,因为程序在代码中实现,不需要增加额外的硬件开支;缺点是需要开发人员来实现,运维人员无从下手。
基于中间代理层实现:代理一般介于应用服务器和数据库服务器之间,代理数据库服务器接收到应用服务器的请求后根据判断后转发到后端数据库。常用的代理程序有mysql_proxy、mysql-mmm、atlas、moeeba、amoeba等。
二. 部署篇
2.1 Yum安装
在导入MySQL源之后,使用yum install在线安装,默认是最新版本,可加上版本号进行控制。由于在线安装较慢,可下载好rpm包,再使用yum localinstall进行解决依赖安装。
[root@node01 ~]# rpm -ivh http://repo.mysql.com/yum/mysql-5.7-community/el/7/x86_64/mysql57-community-release-el7-10.noarch.rpm
[root@node01 ~]# yum localinstall -y mysql-community-server
[root@node01 ~]# systemctl start mysqld
[root@node01 ~]# systemctl enable mysqld
MySQL数据库从5.7的版本开始对密码进行了严格的限制,要求所有用户的密码必须同时包括大小写字母、数字和特殊字符,因为它默认安装了一个validate_password的插件。想要关闭这个插件,在/etc/my.cnf文件中加入一行即可。首次安装MySQL后,要先启动MySQL服务,再禁用validate_password插件,然后重启MySQL服务。
[mysqld]
validate_password=off
mysql_secure_installation安全配置:修改密码,移除匿名用户,禁止root远程,移除test库,重载权限。
[root@node01 ~]# mysql_secure_installation
2.2 源码编译
Mysql5.7版本更新后有很多变化,最主要的变化是安装MySQL必须要有BOOST库,不过MySQL的官网源码包也提供了带BOOST库的源码和不带BOOST库的源码两种。
在安装MySQL之前,需要安装一些MySQL依赖的库文件包。
[root@centos7 ~]# yum install -y gcc gcc-c++ make tar openssl openssl-devel cmake ncurses ncurses-devel bison bison-devel perl perl-devel
通过MySQL官网下载MySQL源码包,这里下载的版本是mysql-boost-5.7.35.tar.gz,下载完成后上传到需要安装的服务器上,进行解压。
[root@centos7 ~]# ls
anaconda-ks.cfg mysql-boost-5.7.35.tar.gz
[root@centos7 ~]# tar xf mysql-boost-5.7.35.tar.gz
MySQL数据库需要以一个普通用户去执行一些操作,因而还需要创建一个普通用户和组。
[root@centos7 ~]# groupadd mysql
[root@centos7 ~]# useradd -r -g mysql -s /bin/false mysql
[root@centos7 ~]# id mysql
uid=997(mysql) gid=1000(mysql) groups=1000(mysql)
从MySQL5.5之后,MySQL的安装就以cmake来代替传统的configure了,下面进入编译环节。
[root@centos7 ~/mysql-5.7.35]# cmake \
-DCMAKE_INSTALL_PREFIX=/usr/local/mysql \
-DMYSQL_DATADIR=/usr/local/mysql/data \
-DDEFAULT_CHARSET=all \
-DDEFAULT_CHARSET=utf8 \
-DDEFAULT_COLLATION=utf8_general_ci \
-DWITH_INNOBASE_STORAGE_ENGINE=1 \
-DWITH_MYISAM_STORAGE_ENGINE=1 \
-DMYSQL_USER=mysql \
-DMYSQL_TCP_PORT=3306 \
-DWITH_BOOST=boost \
-DENABLED_LOCAL_INFILE=1 \
-DWITH_PARTITION_STORAGE_ENGINE=1 \
-DMYSQL_UNIX_ADDR=/tmp/mysqld.sock \
-DWITH_EMBEDDED_SERVER=1
1核1G的配置,make完成一般需要1小时往上,使用make -j会报错。
[root@centos7 ~/mysql-5.7.35]# make
[root@centos7 ~/mysql-5.7.35]# make install
MySQL安装完成后,接下来要做的就是初始化系统库。mysql5.7之前的版本中,初始化脚本位于MySQL主程序安装目录下的scripts目录下,名为mysql_install_db。
而在mysql5.7.x版本中, 此脚本已经废弃,需要通过如下命令完成数据库初始化。
[root@centos7 ~/mysql-5.7.35]# /usr/local/mysql/bin/mysqld --initialize-insecure --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
--initialize-insecure:表示初始化时不生成mysql管理员用户root的密码。
--initialize:表示初始化时生成一个随机密码,此密码默认会显示在mysql的日志文件中。
MySQL的配置文件名为my.cnf,在启动MySQL服务的时候,启动程序默认会首先查找/etc/my.cnf文件,如果找不到会继续搜索"$basedir/my.cnf"文件,其中“$basedir”是MySQL主程序的安装目录。如果还是找不到,最后还会搜索~/.my.cnf文件。
因此,在启动MySQL前需要确认,是否已经存在/etc/my.cnf文件,如 果存在,要先删除原先的/etc/my.cnf文件,然后用新的my.cnf文件启动MySQL。很多MySQL启动失败,都是因为这个原因导致的。
mysql.server脚本用来管理mysql服务器的启动和关闭,使用chkconfig将mysqld加入开机启动项。
[root@centos7 ~]# cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
[root@centos7 ~]# chmod +x /etc/init.d/mysqld
[root@centos7 ~]# chkconfig --add mysqld
[root@centos7 ~]# chkconfig mysqld on
/etc/my.cnf的默认需要需要更改。
[root@centos7 ~]# vim /etc/my.cnf
[mysqld]
datadir=/usr/local/mysql/data
socket=/tmp/mysql.sock
[root@centos7 /usr/local/mysql/support-files]# service mysqld start
Starting MySQL.Logging to '/usr/local/mysql/data/centos7.err'.
SUCCESS!
[root@centos7 ~]# echo 'export PATH=$PATH:/usr/local/mysql/bin' >> /etc/profile
[root@centos7 ~]# source /etc/profile