Linux系统——MySQL基础(二)

# MySQL数据库完全备份与恢复
## 数据库备份的分类
1. 从物理与逻辑的角度,备份可以分为物理备份和逻辑备份。
(1)物理备份:对数据库操作系统的物理文件(数据文件、日志文件)的备份。物理备份又可分为脱机备份(冷备份)和联机备份(热备份)
冷备份:在关闭数据库中的时候进行的
热备份:数据库处于运行状态,这种备份依赖于数据库的日志文件
温备份:数据库锁定表格(不可写入但可读)的状态下进行的
(2)逻辑备份:对数据库逻辑组件(如表等数据库对象)的备份
2. 从数据库的备份策略角度,备份可分为完全备份、差异备份和增量备份
(1)完全备份:每次对数据进行完整的备份
对整个数据库的备份、数据库结构和文件结构的备份,保存的是备份完成时刻的数据库,是差异备份与增量备份的基础。
优点:备份与恢复操作简单方便
缺点:数据存在大量的重复;占用大量的空间;备份与恢复时间长
(2)差异备份:备份那些字从上次完全备份之后被修改过的所有文件
备份的时间节点是从上次完整备份起,备份数据量会越来越大。恢复数据时,只需要恢复上次完全备份与最近的一次差异备份。
(3)增量备份:至于那些在上次完全备份挥着增量备份后被修改的文件才会被备份
以上次完整备份或上次的增量备份的时间为时间点,仅备份这之间的数据辩护啊,因而备份的数量小,占用空间小,备份速度快。但回复是,需要从上一次的完整备份起到左后一次增量备份一次恢复,如中间某次的备份数据损坏,将导致数据的丢失。

## MySQL完全备份操作
1. (冷备份方式)直接打包数据里文件夹
2. (热备份方式)使用专用备份工具mysqldump
(1)对单个库进行完全备份
格式:mysqldump -u用户名 -p密码 选项 空间名 > /备份路径/备份文件名
```
[root@localhost ~]# mysqldump -uroot -p123456 yunjisuan > /tmp/yunjisuan-$(date +%F).sql
[root@localhost ~]# ls /tmp/
mysql.sock yum.log yunjisuan-2018-11-19.sql
```
(2)对多个库进行完全备份
格式:mysqldump -u用户名 -p密码 选项 ==--databases== 空间名1 空间名2 > /备份路径/备份文件名

```
[root@localhost ~]# mysqldump -uroot -p123456 --databases yunjisuan daisy > /tmp/yunjisuan-$(date +%F).sql
```
(3)对所有库进行完全备份
格式:mysqldump -u用户名 -p密码 选项 --all-databases > /备份路径/备份文件名

```
[root@localhost ~]# mysqldump -uroot -p123456 --opt --all-databases > /tmp/yunjisuan-$(date +%F).sql
# --opt 加快备份速度,当备份数据量大时使用
```
(4)对表进行完全备份
格式:mysqldump -u用户名 -p密码 选项 空间名 表名 > /备份路径/备份文件名

```
[root@localhost ~]# mysqldump -uroot -p123456 yunjisuan users > /tmp/yunjisuan-$(date +%F).sql
```
(5)对表结构的备份
格式:mysqldump -u用户名 -p密码 -d 空间名 表名 > /备份路径/备份文件名

```
[root@localhost ~]# mysqldump -uroot -p123456 -d yunjisuan users > /tmp/yunjisuan-$(date +%F).sql
```
## 使用mysqldump备份后,恢复数据库
1. source命令(交互式)

```
[root@localhost ~]# mysqldump -uroot -p123456 --opt --all-databases > /tmp/mysql_all-$(date +%F).sql
[root@localhost ~]# ls /tmp/
mysql_all-2018-11-19.sql
[root@localhost ~]# mysql -uroot -p123456
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| imployee_salary |
| mysql |
| performance_schema |
| test |
| yunjisuan |
+--------------------+
6 rows in set (0.00 sec)
mysql> drop database yunjisuan;
Query OK, 1 row affected (0.01 sec)

mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| imployee_salary |
| mysql |
| performance_schema |
| test |
+--------------------+
5 rows in set (0.00 sec)

mysql> source /tmp/mysql_all-2018-11-19.sql
Query OK, 0 rows affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| imployee_salary |
| mysql |
| performance_schema |
| test |
| yunjisuan |
+--------------------+
6 rows in set (0.00 sec)
```
2. mysql命令(非交互方式)
格式:mysql -u用户名 -p密码 < 库备份脚本的路径
mysql -u用户名 -p密码 库名 < 表备份脚本的路径

```
[root@localhost ~]# mysql -uroot -p123456 -e 'drop database yunjisuan;'
[root@localhost ~]# mysql -uroot -p123456 < /tmp/mysql_all-2018-11-19.sql
[root@localhost ~]# mysql -uroot -p123456 -e 'show databases;'
+--------------------+
| Database |
+--------------------+
| information_schema |
| imployee_salary |
| mysql |
| performance_schema |
| test |
| yunjisuan |
+--------------------+

```
## MySQL备份思路
1. 定期实施备份,指定备份计划或策略,并严格遵守
2. 除了进行完全备份,开启MySQL服务器的日志功能是很重要的(完全备份加上日志,可以对MySQL进行最大化还原)
3. 使用统一和易理解的备份名称,推荐使用库名挥着表名加上时间的命名规则,如mysql_user-20181118.sql,不要使用backup1之类没有意义的名字。

## MySQL增量备份
MySQL是通过二进制日志(mysqlbinlog)实现增量备份的。
一旦开启mysqlbinlog这个日志,用户的每条SQL语句除了select功能,都会被记录
二进制日志在启动MySQL服务器后开始记录,并在文件到达max_binlog_size所设置的大小或者接收到flush logs命令后重新创建新的日志文件。
==控制二进制日志大小==
```
[root@localhost mysql]# vim /etc/my.cnf
53 max_binlog_size=1024000
#二进制日志最大1M
```
只需定时执行flush logs方法重新创建新的日志,生成二进制文件序列,并及时把这些日志保存到安全的地方就完成了一个时间段的增量备份。

开启mysqlbinlog二进制日志功能:
方法一:
```
[root@localhost mysql]# vim /etc/my.cnf
50 log-bin=mysql-bin
113 #log-bin=mysql-bin
```
(1)当在/etc/my.cnf中开启二进制日志功能
(2)当使用SQL语句(除了select功能),/data目录就会产生 mysql-bin.xx的文件
(3)此时,使用mysqlbinlog查看 mysql-bin.xx文件内容

```
[root@localhost mysql]# mysqlbinlog mysql-bin.000006

```

方法二:使用mysqld--log-bin=文件存放路径/文件前缀 重新启动mysql服务
每周选择服务器负载矫情的时间段,或者用户访问较少的时间段进行备份。

### MySQL增量恢复
#### 应用场景
1. 认为的SQL语句破坏了数据库
2. 再进行下一次全北之前发生系统故障导致数据库数据丢失
3. 在主从架构中,主库数据发生了故障

#### 增量恢复的方法
1. 一般的恢复:备份的二进制日志内容全部恢复
格式:mysqlbinlog [--no-defaults] 增量备份文件 | mysql -u 用户名 -p 密码

```
[root@localhost mysql]# mysqlbinlog /usr/local/mysql/data/mysql-bin.000012 | mysql -uroot -p123456
[root@localhost mysql]# mysql -uroot -p123456 -e 'select * from yunjisuan.users;'
+-----------+-------------+
| user_name | user_passwd |
+-----------+-------------+
| daisy | 123456 |
| helen | 432543 |
| 小然 | 533223 |
| 绿小花 | 123123 |
+-----------+-------------+

```

2. 基于时间点的恢复:便于跳过某个发生错误的时间点实现数据恢复
格式:
从日志开头截止到某个时间点的恢复:
mysqlbinlog [--no-defaults] --stop-datetime='年-月-日 小时:分钟:秒' 二进制日志 | mysql -u 用户名 -p 密码
从某个时间点到日志结尾的恢复:
mysqlbinlog [--no-defaults] --start-datetime='年-月-日 小时:分钟:秒' 二进制日志 | mysql -u 用户名 -p 密码
从某个时间点到某个时间点的恢复:
mysqlbinlog [--no-defaults] --start-datetime='年-月-日 小时:分钟:秒' --stop-datetime='年-月-日 小时:分钟:秒' 二进制日志 | mysql -u 用户名 -p 密码

```
mysql> show master status; #查看当前文件字符写在哪个位置
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000013 | 509 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

mysql> delete from yunjisuan.users where user_name='helen';
Query OK, 1 row affected (0.01 sec)

mysql> show master status;
+------------------+----------+--------------+------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000013 | 710 | | |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)

```

3. 基于位置的恢复:可能在同一时间点既有错误的操作也有正确的操作,基于位置进行恢复更加精准
格式:
mysqlbinlog --stop-position='操作 id' 二进制日志 | mysql -u 用户名 -p 密码
mysqlbinlog --start-position='操作 id' 二进制日志 | mysql -u 用户名 -p 密码

```
[root@localhost mysql]# mysql -uroot -p123456 -e 'select * from yunjisuan.users;'
+-----------+-------------+
| user_name | user_passwd |
+-----------+-------------+
| daisy | 123456 |
| helen | 432543 |
| 小然 | 533223 |
| 绿小花 | 123123 |
+-----------+-------------+
[root@localhost mysql]# mysqlbinlog --start-position='509' --stop-position='710' /usr/local/mysql/data/mysql-bin.000013 | mysql -uroot -p123456
[root@localhost mysql]# mysql -uroot -p123456 -e 'select * from yunjisuan.users;'
+-----------+-------------+
| user_name | user_passwd |
+-----------+-------------+
| daisy | 123456 |
| 小然 | 533223 |
| 绿小花 | 123123 |
+-----------+-------------+

```
## 企业备份策略的应用
在企业中应用MySQL的备份策略
1. 中小公司,由于数据量小,数据安全不是特别重要,允许小数量的细节数据丢失。因此,每天尽心过一次数据库的全量备份即可。(定时任务+全备脚本)
2. 中大型公司,由于数据量大,每天全被时间太长,而且。比较关注数据安全和完整,无法承受数据丢失,哪怕只是少量的。对于这种类型的公司,通常采取全量备份+增量备份的方式进行,也就是每周进行一次全量备份(定时任务+全备脚本);每天进行一次增量备份。

中小企业场景,数据库的全量备份如何实现?
第一种:采用rsync备份服务器
数据库的定时任务备份结束以后,自动rsync推送到备份服务器。(要检查数据完整性)
第二种:raid阵列
在MySQL服务器上,额外进行raid磁盘阵列的挂载在/backup上,全备脚本将备份备份在次目录里。

中大型或大型企业,MySQL备份策略如何实现
1. 全备+增备
2. 每周一次全备
3. 增备的实现有两种方式
第一种:通过定时任务+增备切割脚本(每天0点,flush logs)
rsync至少设置两个模块,一个用在全量备份,另一个用在增量备份,先将之前的日志文件打包备份到备份服务器,在进行增量备份,文件与文件之间每天进行一次flush logs,mysql-bin文件里保存的是每天的增量日志,可以设置对增量日志每天打包,进行推送并测试推送数据的完整性,设置一个定时任务,错后一天将前一天的数据包进行删除处理
第二种:不推送,实时同步rsync+inotify
每周日的全量备份结束以后,进行一次flush logs,将mysql-bin.*实时同步到备份服务器上


数据库的常用架构解析:
4. 主从复制
主MySQL数据库通过mysqlbinlog将数据实时同步到备用MySQL数据库上;(读写分离时),将这两台数据库的使用功能区分开,一台专门用来读数据,一台专门用来写数据(减轻数据库的读压力);当一主多从时,需要在从数据库前设置负载均衡器

## MySQL数据库企业 应用实践
### MySQL的多实例应用
1. MySQL多实例就是在一台服务器上同时开启多个不同的服务器端口(如:3306,3307),同时运行多个MySQL服务进程,这些服务进程通过不同的socket监听不同的服务器端口来提供服务。
2. MySQL多实例共用一套MySQL安装程序,使用不同的my.cnf(也可以相同)配置文件,启动程序(也可以相同)和数据文件。在提供服务时,多实例MySQL在逻辑上看起来是各自独立的,它们根据配置文件的对应设定值,获得服务器相应数量的硬件资源。

MySQL多实例的作用
(1)有效利用服务器资源
当单个服务器资源有剩余时,可以充分利用剩余的资源提供更多的服务,且可以实现资源的逻辑隔离。
(2)节约服务器资源
当公司资金紧张,但是数据库又需要各自尽量独立地提供服务,而且,需要主从复制等技术时,多实例就再好不过了。

#### MySQL多实例常见的配置方案
1. 单一配置文件,单一启动程序的多实例部署方案
下面是MySQL官方文档提到的单一配置文件,单一启动程序多实例部署方案,但不推荐此方案,这里仅作为知识点提及,后文不再涉及此方案的说明。my.cnf配置文件示例(MySQL手册里提到的方法)如下:

```
[mysqld_multi]
mysqld = /usr/bin/mysqld_safe
mysqladmin = /usr/bin/mysqladmin
user = mysql
[mysqld1]
socket = /var/lib/mysql/mysql.sock
port = 3306
pid-file = /var/lib/mysql/mysql.pid
datadir = /var/lib/mysql/
user = mysql
[mysqld2]
socket = /mnt/data/db1/mysql.sock
port = 3302
pid-file = /mnt/data/db1/mysql.pid
datadir = /mnt/data/db1/
user = mysql
skip-name-resolv
server-id=10
default-storage-engine=innodb
innodb_buffer_pool_size=512M
innodb_additional_mem_pool=10M
default_character_set=utf8
character_set_server=utf8
#read-only
relay-log-space-limit=3G
expire_logs_day=20
```

启动程序的命令如下:

```
mysqld_multi --config-file=/data/mysql/my_multi.cnf start 1,2
```

该方案的缺点是耦合度太高,一个配置文件,不好管理。工作开发和运维的统一原则为降低耦合度。

2. 多配置文件,多启动程序的部署方案
多配置文件,多启动程序部署方案,是本文主要讲解的方案,也是非常常用并极力推荐的多实例方案。下面来看配置示例。

```
[root@localhost /]# tree /data
/data
├── 3306
│ ├── data #3306实例的数据目录
│ ├── my.cnf #3306实例的配置文件
│ └── mysql #3306实例的启动文件
└── 3307
├── data #3307实例的数据目录
├── my.cnf #3307实例的配置文件
└── mysql #3307实例的启动文件

4 directories, 4 files
```

提示:
这里的配置文件my.cnf,启动程序mysql都是独立的文件,数据文件data目录也是独立的。

#### 安装并配置多实例MySQL数据库
##### 安装MySQL多实例
1. 安装MySQL需要的依赖包和编译软件
(1)安装MySQL需要的依赖包
安装MySQL之前,最好先安装MySQL需要的依赖包,不然后面会出现很多报错信息,到那时还得再回来安装MySQL的依赖包。安装命令如下:

```
[root@localhost ~]# yum -y install ncurses-devel libaio-devel
[root@localhost ~]# rpm -qa ncurses-devel libaio-devel
ncurses-devel-5.7-4.20090207.el6.x86_64
libaio-devel-0.3.107-10.el6.x86_64
```

(2)安装编译MySQL需要的软件
首先通过网络获得cmake软件,然后进行如下操作:

```
[root@localhost ~]# ls -lh cmake-2.8.6.tar.gz
-rw-r--r-- 1 root root 5.4M 7月 19 20:43 cmake-2.8.6.tar.gz #此软件需提前准备
[root@localhost ~]# tar xf cmake-2.8.6.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/cmake-2.8.6/
[root@localhost cmake-2.8.6]# ./configure
[root@localhost cmake-2.8.6]# gmake && gmake install
[root@localhost cmake-2.8.6]# which cmake
```

2. 开始安装MySQL
为了让同学们学习更多的MySQL技术,接下来会以相对复杂的源代码安装来讲解MySQL多实例的安装。大型公司一般都会将MySQL软件定制成rpm包,然后放到yum仓库里,使用yum安装,中小企业里的二进制和编译安装的区别不大。
(1)建立MySQL用户账号
首先以root身份登录到Linux系统中,然后执行如下命令创建mysql用户账号:

```
[root@localhost ~]# useradd -s /sbin/nologin -M mysql
[root@localhost ~]# id mysql
uid=500(mysql) gid=500(mysql) 组=500(mysql)
```

(2)获取MySQL软件包
MySQL软件包的下载地址为:https://dev.mysql.com/downloads/mysql/
提示:
本例以MySQL编译的方式来讲解,之前已经演示过二进制方式安装了。在生产场景中,二进制和源码包两种安装方法都是可以用的,其应用场景一般没什么差别。不同之处在于,二进制的安装包较大,名字和源码包也有些区别,二进制安装过程比源码更快。
MySQL源码包和二进制安装包的名称见下图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119220929495.)
(3)采用编译方式安装MySQL
配置及编译安装的步骤如下:

```
[root@localhost ~]# tar xf mysql-5.5.22.tar.gz -C /usr/src/
[root@localhost ~]# cd /usr/src/mysql-5.5.22/
[root@localhost mysql-5.5.22]# cmake . -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-5.5.22 \
> -DMYSQL_DATADIR=/usr/local/mysql-5.5.22/data \ #数据存放目录
> -DMYSQL_UNIX_ADDR=/usr/local/mysql-5.5.22/tmp/mysql.sock \ #MySQL进程间通信的套接字位置
> -DDEFAULT_CHARSET=utf8 \ #默认字符集为utf8
> -DDEFAULT_COLLATION=utf8_general_ci \ #默认字符集排序规则
> -DEXTRA_CHARSETS=gbk,gb2312,utf8,ascii \ #额外的字符集支持
> -DENABLED_LOCAL_INFILE=ON \ #是否启用加载本地数据
> -DWITH_INNOBASE_STORAGE_ENGINE=1 \ #静态编译innodb存储引擎到数据库
> -DWITH_FEDERATED_STORAGE_ENGINE=1 \ #静态编译FEDERATED存储引擎到数据库
> -DWITH_BLACKHOLE_STORAGE_ENGINE=1 \ #静态编译blackhole存储引擎到数据库
> -DWITHOUT_EXAMPLE_STORAGE_ENGINE=1 \ #不编译EXAMPLE存储引擎到数据库
> -DWITHOUT_PARTITION_STORAGE_ENGINE=1 \ #不支持数据库分区
> -DWITH_FAST_MUTEXES=1 \
> -DWITH_ZLIB=bundled \ #zlib压缩模式
> -DENABLED_LOCAL_INFILE=1 \ #是否启用本地的LOCAL_INFILE
> -DWITH_READLINE=1 \ #使用捆绑的readline
> -DWITH_EMBEDDED_SERVER=1 \ #是否要建立嵌入式服务器
> -DWITH_DEBUG=0 #禁用DEBUG(开启影响性能)
# 提示:编译时可配置的选项很多,具体可参考官方文档
[root@localhost mysql-5.5.22]# make && make install
```

下面设置不带版本号的软链接/usr/local/mysql,操作步骤如下:

```
[root@localhost mysql-5.5.22]# ln -s /usr/local/mysql-5.5.22 /usr/local/mysql
[root@localhost mysql-5.5.22]# ls /usr/local/mysql
bin data include lib mysql-test scripts sql-bench
COPYING docs INSTALL-BINARY man README share support-files
```

如果上述操作未出现错误,查看/usr/local/mysql目录下有内容,则MySQL5.5.22源代码包采用cmake方式的安装就算成功了。

##### 创建MySQL多实例的数据文件目录
在企业中,通常以/data目录作为MySQL多实例总的根目录,然后规划不同的数字(即MySQL实例端口号)作为/data下面的二级目录,不同的二级目录对应的数字就作为MySQL实例的端口号,以区别不同的实例,数字对应的二级目录下包含MySQL的数据文件,配置文件及启动文件等。
下面以配置3306,3307两个实例为例进行讲解。创建MySQL多实例的目录如下:

```
[root@localhost ~]# mkdir -p /data/{3306,3307}/data
[root@localhost ~]# tree /data/
/data/
├── 3306 #3306实例目录
│ └── data #3306实例的数据文件目录
├── 3307 #3307实例目录
└── data #3307实例的数据文件目录


4 directories, 0 files
```

提示:
(1)mkdir -p /data/{3306,3307}/data相当于mkdir -p /data/3306/data;mkdir -p /data/3307/data两条命令
(2)如果是创建多个目录,可以增加如3308,3309这样的目录名,在生产环境中,一般为3~4个实例为佳。

##### 创建MySQL多实例的配置文件
MySQL数据库默认为用户提供了多个配置文件模板,用户可以根据服务器硬件配置的大小来选择。

```
[root@localhost mysql]# ls -l support-files/my*.cnf
-rw-r--r-- 1 root root 4751 7月 19 21:33 support-files/my-huge.cnf
-rw-r--r-- 1 root root 19805 7月 19 21:33 support-files/my-innodb-heavy-4G.cnf
-rw-r--r-- 1 root root 4725 7月 19 21:33 support-files/my-large.cnf
-rw-r--r-- 1 root root 4736 7月 19 21:33 support-files/my-medium.cnf
-rw-r--r-- 1 root root 2900 7月 19 21:33 support-files/my-small.cnf
```

注意:
这些配置文件里的注释非常详细,不过是英文的。。。
上面是单实例的默认配置文件模板,如果配置多实例,和单实例会有不同。为了让MySQL多实例之间彼此独立,要为每一个实例建立一个my.cnf配置文件和一个启动文件MySQL,让他们分别对应自己的数据文件目录data。
首先,通过vim命令添加配置文件内容,命令如下:

```
vim /data/3306/my.cnf
vim /data/3307/my.cnf
```

不同的实例需要添加的my.cnf内容会有区别,其中的配置由官方的配置模板修改而来。当然,在实际工作中,我们是拿早已配置好的模板来进行修改的,可以通过rz等方式上传配置文件模板my.cnf文件到相关目录下。
MySQL3306,3307实例配置文件如下
##实例3306配置文件my.cnf

```
[root@localhost ~]# cat /data/3306/my.cnf
[client]
port = 3306
socket = /data/3306/mysql.sock #.sock 默认放在html目录下,MySQL的实例文件 (通过这个实例文件将socket进程连接在一起;停库后文件不存在,mysql不能启动时,手动pkill .sock文件和pid文件)
[mysqld]
user = mysql
port = 3306
socket = /data/3306/mysql.sock
basedir = /usr/local/mysql
datadir = /data/3306/data
open_files_limit = 1024
back_log = 600
max_connections = 800
max_connect_errors = 3000
table_open_cache = 614
external-locking = FALSE
max_allowed_packet = 8M
#binlog_cache_size = 1M
#max_heap_table_size = 64M
#read_buffer_size = 2M
#read_rnd_buffer_size = 16M
sort_buffer_size = 1M
join_buffer_size = 1M
thread_cache_size = 100
thread_concurrency = 2 #concurrency 并发
query_cache_size = 2M
query_cache_limit = 1M
query_cache_min_res_unit = 2k
#ft_min_word_len = 4
#default-storage-engine = MYISAM
thread_stack = 192K
transaction_isolation = READ-COMMITTED
tmp_table_size = 2M
max_heap_table_size = 2M
#log-bin=mysql-bin
#binlog_format=mixed
#slow_query_log
long_query_time = 1
pid-file = /data/3306/mysql.pid
relay-log = /data/3306/relay-bin
relay-log-info-file = /data/3306/relay-log.info
binlog_cache_size = 1M
max_binlog_cache_size = 1M
max_binlog_size = 2M
key_buffer_size = 16M
read_buffer_size = 1M
read_rnd_buffer_size = 1M
bulk_insert_buffer_size = 1M
0.lower_case_table_names = 1
skip-name-resolve
slave-skip-errors = 1032,1062
replicate-ignore-db = mysql

server-id = 1

#key_buffer_size = 32M
#bulk_insert_buffer_size = 64M
#myisam_sort_buffer_size = 128M
#myisam_max_sort_file_size = 10G
#myisam_repair_threads = 1
#myisam_recover
innodb_additional_mem_pool_size = 4M
innodb_buffer_pool_size = 32M
innodb_data_file_path = ibdata1:128M:autoextend
innodb_file_io_threads = 4
#innodb_write_io_threads = 8
#innodb_read_io_threads = 8
innodb_thread_concurrency = 8
innodb_flush_log_at_trx_commit = 2
innodb_log_buffer_size = 2M
innodb_log_file_size = 4M
innodb_log_files_in_group = 3
innodb_max_dirty_pages_pct = 90
innodb_lock_wait_timeout = 120
innodb_file_per_table = 0

[mysqldump]
quick
max_allowed_packet = 2M

[mysql]
no-auto-rehash

#[myisamchk]
#key_buffer_size = 512M
#sort_buffer_size = 512M
#read_buffer = 8M
#write_buffer = 8M
#[mysqlhotcopy]
#interactive-timeout

[mysqld_safe]
log-error = /data/3306/mysql_yunjisuan3306.err
pid-file = /data/3306/mysqld.pid
```

提示:实例3307的配置文件只需要将3306配置文件里的所有3306数字替换成3307(server-id换个数字)即可。
最终完成后的多实例根/data目录结果如下:

```
[root@localhost ~]# tree /data
/data
├── 3306
│ ├── data
│ └── my.cnf #这个就是3306实例的配置文件
└── 3307
├── data
└── my.cnf #这个就是3307实例的配置文件

4 directories, 2 files
```

##### 创建MySQL多实例的启动文件
MySQL多实例启动文件的创建和配置文件的创建几乎一样,也可以通过vim命令来添加,如下:

```
vim /data/3306/mysql
vim /data/3307/mysql
```

需要添加的MySQL启动文件内容如下。(当然,在实际工作中我们是拿早已配置好的模板来进行修改的,可以通过rz等方式上传配置文件模板MySQL文件到相关目录下)

```
[root@localhost ~]# cat /data/3306/mysql
#!/bin/bash
###############################################
#this scripts is created by Mr.chen at 2016-06-25

port=3306
mysql_user="root"
mysql_pwd="" #这里需要修改为用户的实际密码

CmdPath="/usr/local/mysql/bin"
mysql_sock="/data/${port}/mysql.sock"

#startup function
function_start_mysql(){

if [ ! -e "$mysql_sock" ];then
printf "Starting MySQL....\n"
/bin/sh ${CmdPath}/mysqld_safe --defaults-file=/data/${port}/my.cnf 2>&1 >/dev/null &
else
printf "MySQL is running...\n"
exit
fi
}

#stop function
function_stop_mysql(){

if [ ! -e "$mysql_sock" ];then
printf "MySQL is stopped...\n"
exit
else
printf "Stoping MySQL...\n"
${CmdPath}/mysqladmin -u ${mysql_user} -p${mysql_pwd} -S /data/${port}/mysql.sock shutdown
fi
}

#restart function
function_restart_mysql(){

printf "Restarting MySQL...\n"
function_stop_mysql
sleep 2
function_start_mysql
}

case $1 in
start)
function_start_mysql
;;
stop)
function_stop_mysql
;;
restart)
function_restart_mysql
;;
*)
printf "Usage: /data/${port}/mysql{start|stop|restart}\n"
esac
```

3307实例的启动文件只需修改3306启动文件的端口即可
最终完成后的多实例根/data目录结果如下:

```
[root@localhost ~]# tree /data
/data
├── 3306
│ ├── data
│ ├── my.cnf #3306实例的配置文件
│ └── mysql #3306实例的启动文件
└── 3307
├── data
├── my.cnf #3307实例的配置文件
└── mysql #3307实例的启动文件

4 directories, 4 files
```

需要特别说明一下,在多实例启动文件中,启动MySQL不同实例服务,所执行的命令实质是有区别的,例如,启动3306实例的命令如下:

```
mysqld_safe --defaults-file=/data/3306/my.cnf 2>&1 >/dev/null &
```

启动3307实例的命令如下:

```
mysqld_safe --defaults-file=/data/3307/my.cnf 2>&1 >/dev/null &
```

下面看看在多实例启动文件中,停止MySQL不同实例服务的实质命令。
停止3306实例的命令如下:

```
mysqladmin -uroot -pyunjisuan123 -S /data/3306/mysql.sock shutdown
```

停止3307实例的命令如下:

```
mysqladmin -u root -pyunjisuan123 -S /data/3307/mysql.sock shutdown

```

##### 配置MySQL多实例的文件权限
1)通过下面的命令,授权mysql用户和组管理整个多实例的根目录/data

```
[root@localhost ~]# chown -R mysql.mysql /data
[root@localhost ~]# find /data -name "mysql" | xargs ls -l
-rw-r--r--. 1 mysql mysql 1039 Jul 20 19:33 /data/3306/mysql
-rw-r--r--. 1 mysql mysql 1039 Jul 20 19:34 /data/3307/mysql
```

2)通过下面的命令,授权MySQL多实例所有启动文件的mysql可执行,设置700权限最佳,注意不要用755权限,因为启动文件里有数据库管理员密码,会被读取到。

```
[root@localhost ~]# find /data -name "mysql" | xargs chmod 700
[root@localhost ~]# find /data -name "mysql" | xargs ls -l
-rwx------. 1 mysql mysql 1039 Jul 20 19:33 /data/3306/mysql
-rwx------. 1 mysql mysql 1039 Jul 20 19:34 /data/3307/mysql
```

##### MySQL相关命令加入全局路径的配置
(1)配置全局路径的意义
如果不为MySQL的命令配置全局路径,就无法直接在命令行输入mysql这样的命令,只能用全路径命令(/usr/local/mysql/bin/mysql),这种带着路径输入命令的方式很麻烦。
(2)配置MySQL全局路径的方法
1)确认mysql命令所在路径,命令如下:

```
[root@localhost ~]# ls /usr/local/mysql/bin/mysql
/usr/local/mysql/bin/mysql
```

2)在PATH变量前面增加/usr/local/mysql/bin路径,并追加到/etc/profile文件中,命令如下:

```
[root@localhost ~]# echo 'export PATH=/usr/local/mysql/bin:$PATH' >> /etc/profile
#注意,echo后边是单引号,双引号的话变量内容会被解析掉。
[root@localhost ~]# tail -1 /etc/profile
export PATH=/usr/local/mysql/bin:$PATH
[root@localhost ~]# source /etc/profile
#执行source使上一行添加到/etc/profile中,内容直接生效
#以上命令的用途为定义mysql全局路径,实现在任意路径执行mysql命令
```

提示:
更简单的设置方法为用下面命令做软链接:ln -s /usr/local/mysql/bin/* /usr/local/sbin/,把mysql命令说在路径链接到全局路径/usr/local/sbin/的下面。

##### 初始化MySQL多实例的数据库文件
上述步骤全都配置完毕后,就可以初始化数据库文件了,这个步骤其实也可以在编译安装MySQL之后就操作,只不过放到这里更合理一些。
(1)初始化MySQL数据库
初始化命令如下:

```
[root@localhost scripts]# ./mysql_install_db --basedir=/usr/local/mysql --datadir=/data/3306/data --user=mysql
[root@localhost scripts]# ./mysql_install_db --basedir=/usr/local/mysql --datadir=/data/3307/data --user=mysql
```

提示:
--basedir=/usr/local/mysql为MySQL的安装路径,--datadir为不同的实例数据目录
(2)初始化数据库的原理及结果说明
初始化数据库的实质就是创建基础的数据库系统的库文件,例如:生成MySQL库表等。
初始化数据库后查看对应实例的数据目录,可以看到多了如下文件:

```
[root@localhost scripts]# tree /data

#以下省略若干...
```

##### 启动MySQL多实例的命令

```
[root@localhost scripts]# /data/3306/mysql start
Starting MySQL....
[root@localhost scripts]# /data/3307/mysql start
Starting MySQL....
root@localhost scripts]# netstat -antup | grep 330
tcp 0 0 0.0.0.0:3307 0.0.0.0:* LISTEN 24743/mysqld
tcp 0 0 0.0.0.0:3306 0.0.0.0:* LISTEN 24020/mysqld
```

从输出中可以看到,3306和3307实例均已正常启动。

#### 配置及管理MySQL多实例数据库
##### 配置MySQL多实例数据库开机自启动
服务的开机自启动很关键,MySQL多实例的启动也不例外,把MySQL多实例的启动命令加入/etc/rc.local,实现开机自启动,命令如下:

```
[ root@localhost ~]# echo "#mysql multi instances" >> /etc/rc.local
[root@localhost ~]# echo "/data/3306/mysql start" >> /etc/rc.local
[root@localhost ~]# echo "/data/3307/mysql start" >> /etc/rc.local
[root@localhost ~]# tail -3 /etc/rc.local
#mysql multi instances
/data/3306/mysql start
/data/3307/mysql start

#这里一定要确保MySQL脚本可执行~
```
##### 登陆MySQL测试

```
[root@localhost ~]# mysql -S /data/3306/mysql.sock #直接敲就进来了,而且身份还是root。但是多了-S /data/3306/mysql.sock,用于区别登陆不同的实例
# -S 指定实例位置
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.22 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases; #查看当前所有的数据库
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| test |
+--------------------+
4 rows in set (0.00 sec)
mysql> select user(); #查看当前的登陆用户
25.| user() |
+----------------+
| root@localhost |
+----------------+
1 row in set (0.00 sec)
```
##### MySQL多实例数据库的管理方法
MySQL安装完成后,默认情况下,MySQl管理员的账号root是无密码的。登陆不同的实例需要指定不同实例的mysql.sock文件路径,这个mysql.sock是在my.cnf配置文件里指定的。
下面是无密码情况下登陆数据库的方法,关键点是-S参数及后面指定的/data/33306/mysql.sock,注意,不同实例的sock虽然名字相同,但是路径是不同的,因此是不同的文件。

```
mysql -S /data/3306/mysql.sock
mysql -S /sata/3307/mysql.sock
#-S 指定实例位置,-u 指定数据库 -p 指定密码
```
下面是重启对应实例数据库的命令

```
/data/3306/mysql stop
/data/3307/mysql start
```

##### MySQL安全配置
MySQL管理员的账号root密码默认为空,极不安全,可以通过mysqladmin命令为MySQL不同实例的数据库设置独立的密码,命令如下:

```
[root@localhost ~]# mysqladmin -u root -S /data/3306/mysql.sock password '123123' #为mysql设置密码
[root@localhost ~]# mysql -uroot -p -S /data/3306/mysql.sock #无法直接登陆了
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.5.22 Source distribution

Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

#提示:3307实例设置方法和3306实例相同,只是连接时的mysql,sock路径不同,这已经提醒多次,大家要注意
```

带密码登陆不同实例数据库的方法:

```
#登陆3306实例的命令如下:
mysql -uroot -p123123 -S /data/3306/mysql.sock
#登陆3307实例的命令如下:
mysql -uroot -p123123 -S /data/3307/mysql.sock
```

提示:
基础弱的同学,在测试时尽量保证多实例的密码相同,可以减少麻烦,后面还原数据库时会覆盖密码!
若要重启多实例数据库,也需要进行相应的如下配置。再重启数据库前,需要调整不同实例启动文件里对应的数据库密码。

```
[root@localhost ~]# vim /data/3306/mysql
[root@localhost ~]# sed -n '7p' /data/3306/mysql #这是之前mysql多实例启动脚本里mysql的登陆密码变量
mysql_pwd=""
[root@localhost ~]# sed -i '7 s#""#"123123"#' /data/3306/mysql
[root@localhost ~]# sed -n '7p' /data/3306/mysql
mysql_pwd="123123" #修改成实际的登录密码
[root@localhost ~]# sed -n '7p' /data/3307/mysql
mysql_pwd=""
[root@localhost ~]# sed -i '7 s#""#"123123"#' /data/3307/mysql
[root@localhost ~]# sed -n '7p' /data/3307/mysql
mysql_pwd="123123"
```

多实例下正常停止数据库的命令如下:

```
/data/3306/mysql stop
```

由于选择了mysqladmin shutdown的停止方式,所以停止数据库时需要在启动文件里配置数据库的密码

```
/data/3306/mysql start
```

重点提示:
禁止使用pkill,kill -9,killall -9等命令强制杀死数据库,这会引起数据库无法启动等故障的发生。
##### 如何再增加一个MySQL的实例
若再3306和3307实例的基础上,再增加一个MySQL实例,该怎么办?下面给出增加一个MySQL3308端口实例的命令集合:

```
mkdir -p /data/3308/data
\cp /data/3306/my.cnf /data/3308/
\cp /data/3306/mysql /data/3308/
sed -i 's#3306#3308#g' /data/3308/my.cnf
sed -i 's#server-id = 1#server-id = 8#g' /data/3308/my.cnf
sed -i 's#3306#3308#g' /data/3308/mysql
chown -R mysql:mysql /data/3308
chmod 700 /data/3308/mysql
cd /usr/local/mysql/scripts
./mysql_install_db --datadir=/data/3308/data --basedir=/usr/local/mysql --user=mysql
chown -R mysql:mysql /data/3308
egrep "server-id|log-bin" /data/3308/my.cnf
/data/3308/mysql start

netstat -antup | grep 3308
#提示:最好把server-id按照IP地址最后一个小数点的数字设置
#成功标志:多了一个启动的端口3308
如果配置以后,服务启动后却没有运行起来,别忘了一定要看MySQL错误日志,在/data/3308/my.cnf最下面有错误日志路径地址。
```

##### 多实例MySQL登陆问题分析
(1)多实例本地登录MySQL
多实例本地登录一般通过socket文件来指定具体登陆到哪个实例,此文件的具体位置是在MySQL编译过程或my.cnf文件中指定的。在本地登陆数据库时,登陆程序会通过socket文件来判断登陆的是哪个数据库实例。
例如:通过mysql -uroot -p '123123' -S /data/3307/mysql.sock可知,登陆的是3307这个实例。
mysql.sock文件是MySQL服务器端与本地MySQL客户端进行通信的UNIX套接字文件。
(2)远程连接登陆MySQL多实例
远程登陆MySQL多实例中的一个实例时,通过TCP端口(port)来指定说要登陆的MySQL实例,此端口的配置是在MySQL配置文件my.cnf中指定的。
例如:在mysql -uyunjisuan -p '123123' -h 192.168.200.101 -P 3307中,-P为端口参数,后面接具体的实例端口,端口是一种“逻辑连接位置”,是客户端程序被分派到计算机上特殊服务程序的一种方式,强调提前在192.168.200.101上对yunjisuan用户做了授权。

### MySQL主从复制架构(AB复制)
1. MySQL数据库支持单向,双向,链式级联,环状等不同业务场景的复制。在复制过程中,一台服务器充当主服务器(Master),接收来自用户的内容更新,而一个或多个其他的服务器充当从服务器(Slave),接收来自主服务器binlog文件的日志内容,解析出SQL,重新更新到从服务器,使得主从服务器数据达到一致。
2. 如果设置了链式级联复制,那么,从服务器(Slave)本身除了充当从服务器外,也会同时充当其下面从服务器的主服务器。链式级联复制类似A-->B-->C的复制形式。

下图为单向主从复制架构逻辑图,此架构只能在Master端进行数据写入
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119225136506.)

![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119225152671.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
下图为双向主主复制逻辑架构图,此架构可以在Master1端或Master2端进行数据写入,或者两端同时写入数据(需要特殊设置)
![在这里插入图片描述](https://img-blog.csdnimg.cn/2018111922521087.)
下图为线性级联单向双主复制逻辑架构图,此架构只能在Master1端进行数据写入,工作场景中,Master1和master2作为主主互备,Slave1作为从库,中间的Master2需要做特殊的设置。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119225223576.)
下图为环状级联单向多主同步逻辑架构图,任意一个点都可以写入数据,此架构比较复杂,属于极端环境下的“成品”,一般场景慎用
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119225242563.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
在当前的生产工作中,MySQL主从复制都是异步的复制方式,既不是严格实时的数据同步,但是正常情况下给用户的体验是真实的。

#### MySQL主从复制的企业应用场景
##### 应用场景1:从服务器作为主服务器的实时数据备份
1. 主从服务器架构的设置可以大大加强MySQL数据库架构的健壮性。例如:当主服务器出现问题时,我们可以人工或设置自动切换到从服务器继续提供服务,此时从服务器的数据与宕机时的主数据库几乎是一致的。
2. 这类似NFS存储数据通过inotify + rsync同步到备份的NFS服务器,只不过MySQL的复制方案是其自带的工具。
3. 利用MySQL的复制功能进行数据备份时,在硬件故障,软件故障的场景下,该数据备份是有效的,但对于人为地执行drop,delete等语句删除数据的情况,从库的备份功能就没用了,因为从服务器也会执行删除的语句。
##### 应用场景2:主从服务器实现读写分离,从服务器实现负载均衡
1. 主从服务器架构可通过程序(PHP,java等)或代理软件(mysql-proxy,Amoeba)实现对用户(客户端)的请求读写分离,即让从服务器仅仅处理用户的select查询请求,降低用户查询响应时间,以及同时读写在主服务器上带来的访问压力。对于更新的数据(例如:update,insert,delete语句),则仍然交给主服务器处理,确保主服务器和从服务器保持实时同步。
2. 百度,淘宝,新浪等绝大多数的网站都是用户浏览页面多于用户发布内容,因此通过在从服务器上接收只读请求,就可以很好地减轻主库的读压力,且从服务器可以很容易地扩展为多台,使用LVS做负载均衡效果就非常棒了,这就是传说中的数据库读写分离架构。逻辑架构图如下所示:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119234724616.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
##### 应用场景3:把多个从服务器根据业务重要性进行拆分访问
可以把几个不同的从服务器,根据公司的业务进行拆分。例如:有为外部用户提供查询服务的从服务器,有内部DBA用来数据备份的从服务器,还有为公司内部人员提供访问的后台,脚本,日志分析及供开发人员查询使用的从服务器。这样的拆分除了减轻主服务器的压力外,还可以使数据库对外部用户浏览,内部用户业务处理及DBA人员的备份等互不影响。
#### 实现MySQL主从读写分离的方案
(1)通过程序实现读写分离(性能和效率最佳,推荐)
PHP和Java程序都可以通过设置多个连接文件轻松地实现对数据库的读写分离,即当语句关键字为select时,就去连接读库的连接文件,若为update,insert,delete时,则连接写库的连接文件。
通过程序实现读写分离的缺点就是需要开发人员对程序进行改造,使其对下层不透明,但这种方式更容易开发和实现,适合互联网业务场景。
根据业务重要性拆分从库方案
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119234823358.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
(2)通过开源的软件实现读写分离
MySQL-proxy,Amoeba等代理软件(速度分离调度器 )也可以实现读写分离功能,这些软件的稳定性和功能一般,不建议生产使用。绝大多数公司常用的还是在应用端发程序实现读写分离。
(3)大型门户独立开发DAL层综合软件
百度,阿里等大型门户都有开发牛人,会花大力气开发适合自己业务的读写分离,负载均衡,监控报警,自动扩容,自动收缩等一系列功能的DAL层软件。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181119234847466.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)

#### MySQL主从复制原理介绍
1. MySQL的主从复制是一个异步的复制过程(虽然一般情况下感觉是实时的,实际是有延迟时间的),数据将从一个MySQL数据库(我们称之为Master)复制到另一个MySQL数据库(我们称之为Slave),在Master与Slave之间实现整个主从复制的过程是由三个线程参与完成的。其中有两个线程(SQL线程和I/O线程)在Slave端,另外一个线程(I/O线程)在Master端。
2. 要实现MySQL的主从复制,首先必须打开Master端的binlog记录功能,否则就无法实现。因为整个复制过程实际上就是Slave从Master端获取binlog日志,然后再在Slave上以相同顺序执行获取的binlog日志中所记录的各种SQL操作。
3. 要打开MySQL的binlog记录功能,可通过在MySQL的配置文件my.cnf中的mysqld模块([mysqld]标识后的参数部分)增加“log-bin”参数选项来实现,具体信息如下。

```
[mysqld]
log-bin=/data/3306/mysql-bin
```

提示:
有些同学把log-bin放在了配置文件结尾,而不是[mysqld]标识后,从而导致配置复制不成功。

#### MySQL主从复制原理过程详细描述
下面简单描述MySQL Replication的复制原理过程
1)在Slave服务器上执行start slave命令开启主从复制开关,开始进行主从复制
2)此时,Slave服务器的I/O线程会通过在Master上已经授权的复制用户权限请求连接Master服务器,并请求从指定binlog日志文件的指定位置(日志文件名和位置就是在配置主从复制服务时执行change master命令指定的)之后开始发送binlog日志内容。
3)Master服务器接收到来自Slave服务器的I/O线程的请求后,其上负责复制的I/O线程会根据Slave服务器的I/O线程请求的信息分批读取指定binlog日志文件指定位置之后的binlog日志信息,然后返回给Slave端的I/O线程。返回的信息中除了binlog日志内容外,还有在Master服务器端记录的新的binlog文件名称,以及在新的binlog中的下一个指定更新位置。
4)当Slave服务器的I/O线程获取到Master服务器上I/O线程发送的日志内容,日志文件及位置点后,会将binlog日志内容依次写到Slave端自身的Relay Log(即中继日志)文件(MySQL-relay-bin.xxxx)的最末端,并将新的binlog文件名和位置记录到master-info文件中,以便下一次读取Master端新binlog日志时能够告诉Master服务器从新binlog日志的指定文件及位置开始请求新的binlog日志内容。
5)Slave服务器端的SQL线程会实时检测本地Relay Log中I/O线程新增加的日志内容,然后及时地把Relay Log文件中的内容解析成SQL语句,并在自身Slave服务器上按解析SQL语句的位置顺序执行应用这些SQL语句,并在relay-log.info中记录当前应用中继日志的文件名及位置点。
经过了上面的过程,就可以确保在Master端和Slave端执行了同样的SQL语句。当复制状态正常时,Master端和Slave端的数据是完全一样的。当然,MySQL的复制机制也有一些特殊情况,具体请参考官方的说明,大多数情况下,同学们不用担心。
MySQL Replication的复制原理逻辑图
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181120000731737.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
解析:
左边为主库master,右边为从库slave;
主库有一个master主进程(socket进程)及一个I/O线程;
从库有一个slave主进程,I/O线程及SQL线程。
![在这里插入图片描述](https://img-blog.csdnimg.cn/20181120003319368.?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzMwNDgwNA==,size_16,color_FFFFFF,t_70)
实现复制的过程:
主库:
1. 主库开启二进制日志 log_bin=mysql-bin
用户向主库的data数据目录里写入数据,此时master主库若已打开mysqlbinlog日志,该日志就会记录该数据到mysqlbinlog二进制日志内(I/O线程将用户写在master主库的数据data目录里的数据记录在二进制日志内),开启二进制日志(log_bin=mysql-bin)后,才会有I/O线程。用户向主库的data数据目录里写入数据,此时master主库若已打开mysqlbinlog日志,该日志就会记录该数据到mysqlbinlog二进制日志内(I/O线程将用户写在master主库的数据data目录里的数据记录在二进制日志内),开启二进制日志(log_bin=mysql-bin)后,才会有I/O线程。
2. 创建主从复制账号
3. 主库:server id=1
从库:
4. 从库开启中继日志 relay-log=relay-bin
从库的I/O线程紧盯主库的二进制日志,一旦有更新,从库的I/O线程就会向主库的I/O线程申请验证,验证通过后,主库的I/O线程就会把对应的mysqlbinlog二进制日志内容复制给从库的I/O线程,从库的I/O线程把复制的内容存放在中继日志relay-log从库的I/O线程紧盯主库的二进制日志,一旦有更新,从库的I/O线程就会向主库的I/O线程申请验证,验证通过后,主库的I/O线程就会把对应的mysqlbinlog二进制日志内容复制给从库的I/O线程,从库的I/O线程返还的信息有binlog日志内容(复制的内容)及新的binlog文件和POS值(position);从库的I/O线程把复制的内容(binlog日志内容)存放在中继日志relay-log
验证信息:
(1)主库IP
(2)主库socket进程的端口号
(3)主库的复制账号和密码
(4)复制哪个二进制文件的名字
(5)二进制日志文件中position具体位置
验证信息录入到从库后,从库信息记录在master.info(记录验证信息和二进制日志文件位置信息)
5. 此时SQL线程开始启动,查看中继日志,将中继日志中的二进制翻译成一条一条的SQL语句,跟踪relay-bin,SQL线程使用relay-log.info做记录
,执行从库的mysql/data,从而完成主从复制的过程。
6. 主从复制验证信息录入
7. 在从库中激活主从复制
8. 从库:server id=不为1 的值

 

特别说明:
当企业面试MySQL主从复制原理时,不管是面试还是笔试,都要尽量画图表达,而不是口头讲或文字描述,面试时可以找黑板或拿出纸来给面试官详细讲解。


下面针对MySQL主从复制原理的重点进行小结:
10. 主从复制是异步的逻辑的SQL语句级的复制
11. 复制时,主库有一个I/O线程,从库有两个线程,即I/O和SQL线程
12. 实现主从复制的必要条件是主库要开启记录binlog功能
13. 作为复制的所有MySQL节点的server-id都不能相同。
14. binlog文件只记录对数据库有更改的SQL语句(来自主数据库内容的变更),不记录任何查询(如select,show)语句。

 

posted @ 2018-11-25 23:33  daisy118  阅读(205)  评论(0编辑  收藏  举报