高性能MySQL总结

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了高性能MySQL总结相关的知识,希望对你有一定的参考价值。

目录

  1. MySQL主从复制
  2. 复制过滤器
  3. 复制与监控
  4. 主从复制的读写分离
  5. 备份与恢复
  6. 表分区

一、mysql主从复制

复制拓扑:

主机 IP 备注
Mysql-master.linux.com 192.168.239.142 master
Mysql-slave.linux.com 192.168.239.143 slave

1、创建复制账号

连接主数据库服务器,创建具有replication slave和replication client权限的账号。

[[email protected] ~]# mysql
mysql> grant replication slave,replication client on *.* to [email protected]‘192.168.239.%‘ identified by ‘centos‘;

2、配置主从节点

主节点:

[[email protected] ~]# vim /etc/my.cnf 

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# 新增加如下两行
log_bin=/data/mysql/logs/mysql-bin
server_id=10

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

log_bin指定生成的二进制日子文件的目录和文件名
server_id指定唯一标识的数据库ID
从节点:

[[email protected] ~]# vim /etc/my.cnf 

[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

# 新增如下
server_id=20
relay_log=/data/mysql/logs/mysql-relay-bin
read_only=1

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

relay_log指定中继日志的目录和文件名
最后重启主从数据库服务。

3、从节点连接主节点

[[email protected] ~]# mysql

mysql> change master to master_host=‘192.168.239.142‘,master_user=‘replicater‘,master_password=‘centos‘,master_log_file=‘mysql-bin.000003‘,master_log_pos=283;

其中master_log_file和master_log_pos可以根据主节点的show master status语句查询到。
技术分享图片

[[email protected] ~]# mysql
mysql> show slave statusG;

可以看到从节点的IO线程和SQL线程并没有启动。那是因为还没有启动从节点的复制。
技术分享图片
接下启动从节点的复制,可以看到从节点的IO线程和SQL线程启动。

mysql> start slave;

技术分享图片
到此为止MySQL主从复制已经配置完成,以后只要主机节点的数据发生变化,从节点也会跟着变化。例如:
技术分享图片
接着从节点也会相应的生成mydb数据库。
技术分享图片
另外也可以看到读取二进制文件的位置也发生了变化。(从283增长为336)
技术分享图片


二、复制过滤器

1、主库过滤

在主库上进行过滤只能针对数据库进行限制,而无法针对表进行过滤。
binlog_do_db=指定更新数据写入二进制日志文件的数据库,白名单
binlog_ignore_db=指定更新数据不写入二进制文件的数据库,黑名单

2、从库过滤

从库的SQL线程只对关心的数据库,表进行重放,以此来实现从库的过滤,可以发现,从库过滤不仅可是针对数据库,也可以针对表。
Replicate_Do_DB=
Replicate_Ignore_DB=

Replicate_Do_Table=
Replicate_Igonre_Table=

Replicate_Wild_Do_Table=
Replicate_Wild_Ignore_Table=


三、复制的监控与维护

随着时间的推移,数据库中的日志文件会日积月累,并且会占用大量的磁盘空间。因此就需要对一些日志文件进行管理。

1、清理日志

对于数据库的二进制日志文件,不能简单地使用rm命令进行删除,如果直接删除的话,用于记录二进制日志文件的index文件没有修改,这会造成数据库复制时候的错误。因此需要使用专门的工具清理日志。
命令PURGE:
格式:PURGE MASTER|BINARY LOGS TO ‘log_name‘
技术分享图片
技术分享图片

2、复制监控

主库:
?SHOW MASTER STATUS;
?SHOW BINLOG EVENTS;
?SHOW BINARY LOGS;
技术分享图片
技术分享图片
技术分享图片
从库:
?SHOW SLAVE STATUSG;
技术分享图片
其中的Seconds_Behind_Master参数表示从库落后于主库多长时间。解决主从数据不一致的问题可以尝试重新启动SQL线程。


四、主从复制的读写分离

借助SQL router(read/write spliter)实现。
目前实现MySQL集群读写分离的中间件很多,这里用ProxySQL来实现读写分离。
环境拓扑:

IP地址 角色
192.168.239.129 ProxySQL主机
192.168.239.142 mysql主节点
192.168.239.143 mysql从节点

具体操作:

1、mysql主从节点实现主从复制

这一步骤引用一、MySQL主从复制的例子

2、安装ProxySQL中间件

ProxySQL的下载地址为https://github.com/sysown/proxysql/releases
上边有对应的操作系统的版本,下载即可

[[email protected] src]# pwd
/usr/local/src
[[email protected] src]# ls proxysql-1.4.10-1-centos67.x86_64.rpm 
proxysql-1.4.10-1-centos67.x86_64.rpm
[[email protected] src]# yum -y install proxysql-1.4.10-1-centos67.x86_64.rpm

ProxySQL提供了如下的文件。其中的/etc/proxysql.cnf文件是proxysql服务启动时候的初始化配置。
技术分享图片
下边的操作可以直接全部在/etc/proxysql.cnf中直接配置,启动proxysql服务就可以一步到位;当然还可以通过管理端(下边有提到)连接ProxySQL,通过SQL语句一步一步的完成配置。
这里通过/etc/proxysql.cnf完成。

3、创建ProxySQL管理账号

ProxySQL会启动两种类型的端口,一类管理端口,用于管理配置ProxySQL,仅限本地登录;一类客户端口,用于连接后端的mysql。他们默认分别监听在6032和6033端口。
首先配置ProxySQL的管理端,创建管理账号。
添加如下内容:
技术分享图片
其中

参数 作用
admin_credentials 指定连接管理端的用户和密码
mysql_ifaces 指定连接管理端的IP和端口

4、配置后端的mysql

相关的配置内容如下:

mysql_servers =
(
    {
        address = "192.168.239.142" # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
        port = 3306           # no default, required . If port is 0 , address is interpred as a Unix Socket Domain
        hostgroup = 1           # no default, required
        status = "ONLINE"     # default: ONLINE
        weight = 1            # default: 1
        compression = 0       # default: 0
    max_replication_lag = 10  # default 0 . If greater than 0 and replication lag passes such threshold, the server is shunned
    },
    {
        address = "192.168.239.143"
        port = 3306
        hostgroup = 2
        status = "ONLINE"
        weight = 1
        compression = 0
        max_replication_lag = 10
    }
)

address?指定后端mysql的IP地址
port?指定后端mysql的port
hostgroup?指定该mysql的组id,这里规划的是1组进行写操作,2组进行读操作

5、创建连接mysql的账户

这一步操作需要在后端的两台mysql主机分别进行。分别创建连接账户proxysql,并赋予该账户全部权限。并且该账户也可以通过登录ProxySQL主机然后连接后端mysql。
主节点:

[[email protected] ~]# mysql 
([email protected]) [none]> grant all on *.* to [email protected]‘192.168.239.%‘ identified by ‘proxysql‘;

从节点:

[[email protected] ~]# mysql 
([email protected]) [none]> grant all on *.* to [email protected]‘192.168.239.%‘ identified by ‘proxysql‘;

然后将连接mysql的账户proxysql添加到ProxySQL主机,ProxySQL主机就是通过这个账号连接后端mysql并进行操作。在/etc/proxysql.cnf添加如下内容,

mysql_users:
(
    {
        username = "proxysql" # no default , required
        password = "proxysql" # default: ‘‘
        default_hostgroup = 1 # default: 0
        active = 1            # default: 1
    }
)

default_hostgroup=1表示ProxySQL主机默认将SQL事件调度到1组,一般为进行写操作的那个组。

6、添加规则到ProxySQL主机

在/etc/proxysql.cnf中添加如下内容:

mysql_query_rules:
(
    {
        rule_id=1
        active=1
        match_pattern="^SELECT .* FOR UPDATE$"
        destination_hostgroup=1
        apply=1
    },
    {
        rule_id=2
        active=1
        match_pattern="^SELECT"
        destination_hostgroup=2
        apply=1
    }
)

select开头的查询语句调度到2组(即读操作的组),但是特别注意select ... for update之类的语句,也是会修改数据,因此需要将其调度到1组(即写操作的组),剩下的SQL语句全部调度到default_hostgroup定义的默认组。
关于是否定义监控用户,简单起见,这里没有在后端mysql中创建,监控用户可以用来监控后端mysql节点的状态信息,并且可以根据后端mysql的read_only参数自动地将其定义为只读组。还有因为这里将读组和写组已经定义在mysql_servers =中,因此也无需创建监控用户。
/etc/proxysql.cnf的其他内容保持默认。然后启动proxysql服务。

7、测试读写分离

通过proxysql账户连接ProxySQL主机,分别进行相关的查询操作和更改数据的操作,

[[email protected] ~]# mysql -uproxysql -h127.0.0.1 -P6033 -pproxysql
([email protected]) [(none)]> select user,host from mysql.user;
([email protected]) [(none)]> create database mydb2;

然后通过管理账户登录ProxySQL查看具体的连接状态

[[email protected] ~]# mysql -uadmin -h127.0.0.1 -P6032 -padmin
([email protected]) [(none)]> select * from stats_mysql_query_digest;

可以看到读操作调度到了2组,写操作调度了1组。读写分离成功。
技术分享图片


五、备份与恢复

5.1 逻辑备份工具mysqldump

mysqldump是mysql自带的用于逻辑备份的工具。
技术分享图片
下面是mysqldump工具常用方式的几个实例:

1. 备份所有数据库到单个文件

# 将192.168.239.143主机的mysql上所有库备份到本地root/backup目录的dump.sql文件
mysqldump --user=root --host=192.168.239.143 --password=centos --all-databases > /root/backup/dump.sql

2. 备份单个数据库到单个文件

# 将192.168.239.143主机的mysql上的mydb库备份到本地的dump.sql文件
mysqldump --user=root --host=192.168.239.143 --password=centos --databases mydb > /root/backup/dump.sql

3. 备份单个数据表到单个文件

# 将192.168.239.143主机上的mysql的mydb中的mytbl表备份到本地dump.sql文件
mysqldump --user=root --host=192.168.239.143 --password=centos --databases mydb --tables mytbl > /root/backup/dump.sql
# 将备份的单个文件恢复到mydb库中
mysql -u root mydb < /root/backup/dump.sql

如果恢复mysqldump备份的表出现了错误:ERROR 1046 (3D000) at line 22: No database selected,这是因为命令行中没有指定将表恢复到哪个数据库中。

4. mysqldump全量备份+mysqlbinlog增量备份

首先需要开启mysql服务的二进制日志功能,在/etc/my.cnf中添加log_bin=/data/mysql/logs/mysql-bin

[[email protected] ~]# mkdir -p /data/mysql/logs
[[email protected] ~]# chown mysql.mysql /data/mysql/logs

在某一时候对所有数据库做全量备份,

[[email protected] ~]# mysqldump --single-transaction  --flush-logs --master-data=2 --user=root --host=127.0.0.1 > /root/backup/dump.`date +%F`.sql
[[email protected] ~]# cd /root/backup/
[[email protected] backup]# ls
dump.2018-08-31.sql

查看全量备份的数据信息,
技术分享图片
现在再次增加新的数据,

([email protected]) [(none)]> insert into mydb.mytbl value (6,‘huangzhong‘,90),(7,‘zhugeliang‘,20);

技术分享图片
因为误操作导致删除了所有数据库,

[[email protected] ~]# rm -rf /var/lib/mysql/*

技术分享图片
到这里,如果仅仅依靠全量备份进行恢复,则mysql只能回到备份时刻点的数据,之后新增的数据并无法恢复,因此还需要借助二进制文件生成增量备份。
现在开始做增量备份,需要使用最新生成的二进制文件。

[[email protected] ~]# mysqlbinlog /data/mysql/logs/mysql-bin.000001 > /root/backup/mysql-bin.000001.sql

这样在/root/backup/目录下存在两个sql文件,一个全量备份,一个增量备份。
现在开始恢复删库之前的所有数据。
重启mysqld服务,

[[email protected] backup]# /etc/init.d/mysqld restart
[[email protected] backup]# mysql < /data/backup/dump.2018-08-31.sql
# 恢复全量备份之后,数据库中还没有后来新增的那两条数据
[[email protected] backup]# mysql < /data/backup/mysql-bin.000001.sql
# 恢复增量备份,恢复新增的数据

技术分享图片

5.2 物理备份工具Xtrabackup

Xtrabackup的下载地址:https://www.percona.com/downloads/XtraBackup/LATEST/

1. xtrabackup全量备份与恢复

利用Xtrabackup工具中的innobackupex命令进行数据库的全量备份,完成之后会在指定目录下生成一个备份目录

[[email protected] ~]# innobackupex --user=root /root/backup/
[[email protected] ~]# cd /root/backup/
[[email protected] backup]# ls
2018-08-31_02-17-02

可以发现备份目录和原来数据库中的数据相似。
技术分享图片
进行准备阶段,到了第二个阶段后,可以不用连接mysql。因此暂停mysql服务。
准备阶段的格式:innobackupes --appply-log <生成的全备份目录>

[[email protected] 2018-08-31_02-17-02]# /etc/init.d/mysqld stop
[[email protected] 2018-08-31_02-17-02]# innobackupex --apply-log /root/backup/2018-08-31_02-17-02/

因为误操作删除了所有数据库,

[[email protected] 2018-08-31_02-17-02]# rm -rf /var/lib/mysql/*

进行恢复,

[[email protected] 2018-08-31_02-17-02]# innobackupex --copy-back /root/backup/2018-08-31_02-17-02/

总之xtrabackup工具进行恢复数据操作经历三个阶段:备份、准备、恢复。当看到completed OK!字样就表示每个阶段执行成功。
完成之后在数据目录下生成的文件和目录的所属人和所属组都是root,需要将他们改为mysql

[[email protected] mysql]# chown -R mysql.mysql /var/lib/mysql/*

然后启动mysql,可以看到数据又回来了。

([email protected]) [(none)]> select * from mydb.mytbl;

技术分享图片

2. xtrabackup增量备份与恢复

以上例的全量备份为基准,以此来做增量备份,

[[email protected] ~]# mkdir /root/backup/incremental
[[email protected] ~]# innobackupex --user=root  --incremental /root/backup/incremental --incremental-basedir=/root/backup/2018-08-31_02-17-02/

再次在数据库中插入新的数据,
技术分享图片
再做一次增量备份,这次以上一次的增量备份为基准,

[[email protected] incremental]# innobackupex --user=root --incremental /root/backup/incremental --incremental-basedir=/root/backup/incremental/2018-08-31_03-02-49/

这样就生成了两个增量备份文件。
技术分享图片
因为误操作删除了所有数据库

[[email protected] ~]# rm -rf /var/lib/mysql/*

现在开始进行恢复操作。首先暂停mysql服务
1、对全量备份进行准备

[[email protected] ~]# innobackupex --apply-log --redo-only /root/backup/2018-08-31_02-17-02

2、合并增量备份,将两个增量备份添加到全量备份中

# 增量1增加到全量备份
[[email protected] ~]# innobackupex --apply-log --redo-only /root/backup/2018-08-31_02-17-02 --incremental-dir=/root/backup/incremental/2018-08-31_03-02-49
# 增量2增加到全量备份
[[email protected] ~]# innobackupex --apply-log /root/backup/2018-08-31_02-17-02/ --incremental-dir=/root/backup/incremental/2018-08-31_03-10-59/

3、对添加了增量备份的全量备份进行准备

[[email protected] ~]# innobackupex --apply-log /root/backup/2018-08-31_02-17-02/

4、开始恢复

[[email protected] ~]# innobackupex --copy-back /root/backup/2018-08-31_02-17-02/
[[email protected] ~]# chown -R mysql.mysql /var/lib/mysql/*

现在再来查看回复后的数据库,可以发现所有的数据都回来了。
技术分享图片
注:其中--redo-only 的意义--> 在“准备基本完整备份” 和 “合并所有的增量备份(除了最后一个增备)”时使用此选项。它直接传递给xtrabackup的 xtrabackup --apply-log-only 选项,使xtrabackup跳过"undo"阶段,只做"redo"操作。如果后面还有增量备份应用到这个全备,这是必要的。


六、表分区

MySQL支持四种分区类型,分别为:
 RANGE分区
 LIST分区
 HASH分区
 KEY分区

1、range分区类型

该种分区类型是基于连续的值进行分区.
例如创建students表,并且基于id进行分区,id小于101,id小于201,id小于301的三个分区表。

([email protected]) [mydb1]> create table students (id INT,name char(20),grade float(3,1)) partition by range (id) ( partition p0 values less than (101),partition p1 values less than (201),partition p2 values less than (301) );

技术分享图片
技术分享图片

2、list分区类型

该种分区类型是基于离散的值进行分区。
例如创建cla***ooms表,其中room-id为11,12,13,14的在pfirst分区表,21,22,23,24的在psecond分区表,31,32,33,34的在pthird分区表。

([email protected]) [mydb1]> create table cla***ooms (id INT,leader char(20)) partition by list(id) ( partition pfirst values in (11,12,13,14),partition psecond values in (21,22,23,24),partition pthird values in (31,32,33,34) );

技术分享图片

3、hash分区类型

该种分区类型是基于不同的值进行hash运算,再通过hash值进行分区。hash分区的键必须为整数。
例如创建teachers表,其中根据id字段值进行hash运算,语法格式为:partition by hash (expression) partitions num。expresssion表示一个返回整数的表达式,num表示分区的数量。

([email protected]) [mydb1]> create table teachers (id INT,name char(20),age TINYINT) partition by hash (id) partitions 3;

4、key分区类型

该种分区类型也是基于不同的值进行hash运算,和hash分区不同的是,key分区支持非整数的键。

([email protected]) [mydb1]> create table employee (name char(20),birthday date,job char(30)) partition by  key (birthday) partitions 3;

以上是关于高性能MySQL总结的主要内容,如果未能解决你的问题,请参考以下文章

BootStrap实用代码片段(持续总结)

高性能MySQL总结

回归 | js实用代码片段的封装与总结(持续更新中...)

高性能MySQL之第十六章MySQL用户工具总结

构建高性能MYSQL集群系统总结

MySQL高性能优化实战总结