Mysql实战
介绍
MySQL 是应用最广泛的开源关系数据库,是许多常见网站、应用程序和商业产品使用的主要关系数据存储。MySQL 有 20 多年的社区开发和支持历史,是一种可靠、稳定而安全的基于 SQL 的数据库管理系统。MySQL 数据库适用于各种使用案例,包括任务关键型应用程序、动态网站以及用于软件、硬件和设备的嵌入式数据库。
下载
软件包列表:
MySQL-client-5.6.24-1.el6.x86_64.rpm
MySQL-server-5.6.24-1.el6.x86_64.rpm
mysql-connector-java-5.1.27.tar.gz
: 操作系统选择Platform Independent
(平台无关)
安装(Centos7)
1、卸载旧版本
1 | rpm -qa|grep mysql # 查看 |
2、安装服务端
1 | rpm -ivh MySQL-server-5.6.24-1.el6.x86_64.rpm |
3、安装客户端
1 | rpm -ivh MySQL-client-5.6.24-1.el6.x86_64.rpm |
4、user配置
1 | use mysql; |
5、配置文件
配置文件位置,Linux默认在/etc/my.cnf
,如果找不到通过一下命令查找:
1 | 两种方式都可以查找my.cnf位置 |
修改配置文件:
1 | [client] |
log-bin=mysql-bin
这个表示binlog日志的前缀是mysql-bin,以后生成的日志文件就是 mysql-bin.000001 的文件后面的数字按顺序生成,每次mysql重启或者到达单个文件大小的阈值时,新生一个文件,按顺序编号。
使用
TODO
原理
MYSQL执行顺序
MySQL的语句一共分为11步,如下图所标注的那样,最先执行的总是FROM操作,最后执行的是LIMIT操作。其中每一个操作都会产生一张虚拟的表,这个虚拟的表作为一个处理的输入,只是这些虚拟的表对用户来说是透明的,但是只有最后一个虚拟的表才会被作为结果返回。如果没有在语句中指定某一个子句,那么将会跳过相应的步骤。
下面我们来具体分析一下查询处理的每一个阶段
- FORM: 对FROM的左边的表和右边的表计算笛卡尔积。产生虚表VT1。
- ON: 对虚表VT1进行ON筛选,只有那些符合的行才会被记录在虚表VT2中。
- JOIN: 如果指定了OUTER JOIN(比如left join、 right join),那么保留表中未匹配的行就会作为外部行添加到虚拟表VT2中,产生虚拟表VT3, rug from子句中包含两个以上的表的话,那么就会对上一个join连接产生的结果VT3和下一个表重复执行步骤1~3这三个步骤,一直到处理完所有的表为止。
- WHERE: 对虚拟表VT3进行WHERE条件过滤。只有符合的记录才会被插入到虚拟表VT4中。
- GROUP BY: 根据group by子句中的列,对VT4中的记录进行分组操作,产生VT5。
- CUBE | ROLLUP: 对表VT5进行cube或者rollup操作,产生表VT6。
- HAVING: 对虚拟表VT6应用having过滤,只有符合的记录才会被 插入到虚拟表VT7中。
- SELECT: 执行select操作,选择指定的列,插入到虚拟表VT8中。
- DISTINCT: 对VT8中的记录进行去重。产生虚拟表VT9。
- ORDER BY: 将虚拟表VT9中的记录按照进行排序操作,产生虚拟表VT10。
- LIMIT:取出指定行的记录,产生虚拟表VT11, 并将结果返回。
1 | SQL查询处理的步骤序号: |
Mysql的binlog
binlog介绍
MySQL的二进制日志可以说MySQL最重要的日志了,它记录了所有的DDL和DML(除了数据查询语句)语句,以事件形式记录,还包含语句所执行的消耗的时间,MySQL的二进制日志是事务安全型的。
一般来说开启二进制日志大概会有1%的性能损耗。二进制有两个最重要的使用场景:
- MySQL Replication在Master端开启binlog,Master把它的二进制日志传递给slaves来达到master-slave数据一致的目的。
- 数据恢复,通过使用mysqlbinlog工具来使恢复数据。
二进制日志包括两类文件:二进制日志索引文件(文件名后缀为.index)用于记录所有的二进制文件,二进制日志文件(文件名后缀为.00000*)记录数据库所有的DDL和DML(除了数据查询语句)语句事件。
Binlog的分类
binlog的格式也有三种:STATEMENT
、ROW
、MIXED
。
STATMENT
模式:基于SQL语句的复制(statement-based replication, SBR),每一条会修改数据的sql语句会记录到binlog中。
优点:不需要记录每一条SQL语句与每行的数据变化,这样子binlog的日志也会比较少,减少了磁盘IO,提高性能。
缺点:在某些情况下会导致master-slave中的数据不一致(比如:delete from t where a>=4 and t_modified<='2018-11-10' limit 1;
在主库执行这个语句的时候,如果使用的是a索引,会删除(4,4,'2018-11-10')
这条记录,如果使用的是t_modified的索引则会删除insert into t values(5,5,'2018-11-09');
所以在执行这条sql语句的时候提示:Unsafe statement written to the binary log using statement format since BINLOG_FORMAT = STATEMENT. The statement is unsafe because it uses a LIMIT clause. This is unsafe because the set of rows included cannot be predicted.
由于 statement 格式下,记录到 binlog 里的是语句原文,因此可能会出现这样一种情况:在主库执行这条 SQL 语句的时候,用的是索引 a;而在备库执行这条 SQL 语句的时候,却使用了索引 t_modified。因此,MySQL 认为这样写是有风险的。sleep()
函数,last_insert_id()
,以及user-defined functions(udf)
等也会出现问题);ROW
基于行的复制(row-based replication, RBR)格式:不记录每一条SQL语句的上下文信息,仅需记录哪条数据被修改了,修改成了什么样子了。
优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题。
缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨。MIXED
混合模式复制(mixed-based replication, MBR):以上两种模式的混合使用,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog,MySQL会根据执行的SQL语句选择日志保存方式。
可以看到
ROW
模式下,binlog日志中的begin和commit之间并没有sql语句。
在STATEMENT
模式下,binlog日志中的begin和commit之间是一条sql语句。
事务隔离级别
详情见: 本地事务.md
主从同步
主服务器配置
配置:
1 | $ vim my.cnf |
授权:
1 | # 允许从服务器同步数据的账户 user 123456 |
show master status
获取到日志名和偏移量,在从数据库启动后从这个点开始进行数据恢复。
从服务器配置
配置:
1 | $ vim my.cnf |
执行同步:
1 | mysql> change master to master_user='user', # 授权用户 |
其他配置
开启远程访问权限
一、开启mysql远程访问
授予用户user 密码 passwd 所有权限 所有主机IP可访问
- 授权语句:Grant <权限> on 表名[(列名)] to 用户 With grant option或 GRANT <权限> ON <数据对象> FROM <数据库用户>
1 | GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'passwd' WITH GRANT OPTION; |
- ALL PRIVILEGES表示所有权限,*.*表示所有数据库和表,
%
表示所有IP,WITH GRANT OPTION授予授权权限,如果想让授权的用户,也可以将这些权限 grant 给其他用户,需要选项 “grant option“。
只能访问数据库gogs的所有权
1 | GRANT ALL PRIVILEGES ON gogs.* TO 'user2'@'%' IDENTIFIED BY 'passwd2' WITH GRANT OPTION; |
分别授予用户所有主机IP可访问,分别拥有增删改查权限
1 | GRANT select ON *.* TO 'user1'@'%' IDENTIFIED BY 'passwd1' WITH GRANT OPTION; |
查询用户具有的权限,因为只给了查询权限,所以只有Select_priv: Y。
1 | mysql> GRANT select ON *.* TO 'user'@'%' IDENTIFIED BY 'passwd' WITH GRANT OPTION; |
二、撤销已经赋予给 MySQL 用户权限的权限。
revoke 跟 grant 的语法差不多,只需要把关键字 “to” 换成 “from” 即可:
1 | grant all on *.* to dba@localhost; |
grant, revoke 用户权限后,该用户只有重新连接 MySQL 数据库,权限才能生效。
三、对数据库开启只读权限,用于数据库热备份
1、 对于MySQL单实例数据库和master库,如果需要设置为只读状态,需要进行如下操作和设置:
将MySQL设置为只读状态的命令:
1 | mysql> show global variables like "%read_only%"; |
将MySQL从只读状态设置为读写状态的命令:
1 | mysql> unlock tables; |
2)、对于需要保证master-slave主从同步的salve库
将slave从库设置为只读状态,需要执行的命令为:
1 | mysql> set global read_only=1; |
将salve库从只读状态变为读写状态,需要执行的命令是:
1 | mysql> set global read_only=0; |
授权
授权格式:
1 | GRANT <privileges> ON <dbName.tableName> TO <user> [IDENTIFIED BY "<password>"] [WITH GRANT OPTION]; |
授权参数讲解:
privilegesCode表示授予的权限类型,常用的有以下几种类型:
- all privileges:所有权限。
- select:读取权限。
- delete:删除权限。
- update:更新权限。
- create:创建权限。
- drop:删除数据库、数据表权限。
dbName.tableName表示授予权限的具体库或表,常用的有以下几种选项:
*.*:授予该数据库服务器所有数据库的权限。
dbName.*:授予dbName数据库所有表的权限。
dbName.dbTable:授予数据库dbName中dbTable表的权限。
username@host 表示授予的用户以及允许该用户登录的IP地址。其中Host有以下几种类型:
- localhost:只允许该用户在本地登录,不能远程登录。
- %:允许在除本机之外的任何一台机器远程登录。
- 192.168.52.32:具体的IP表示只允许该用户从特定IP登录。
password指定该用户登录时的面。
flush privileges表示刷新权限变更。
1、查看所有用户以及授权主机
1 | mysql> select User,Host from mysql.user; |
2、查看某个用户的授权情况
1 | mysql> show grants for 'root'@'localhost'; |
或者
1 | mysql> show grants for 'zabbix'@'%'; |
3、授权
- 授权所有权限
1 | GRANT ALL PRIVILEGES ON *.* TO 'user'@'%' IDENTIFIED BY 'passwd' WITH GRANT OPTION; |
- 授权单个gogs库权限
1 | GRANT ALL PRIVILEGES ON gogs.* TO 'user2'@'%' IDENTIFIED BY 'passwd2'; |
- 授权单个user表权限
1 | GRANT ALL PRIVILEGES ON gogs.user TO 'user2'@'%' IDENTIFIED BY 'passwd2' WITH GRANT OPTION; |
- 单独授权增删改查权限,而不是所有权限
1 | grant select, insert, update, delete on gogs.* to user@'%'; |
- 授权某个固定主机权限
1 | grant select, insert, update, delete on gogs.* to user@'172.16.3.200'; |
4、取消授权
1 | revoke ALL PRIVILEGES ON *.* from 'user'@'%'; |
5、删除用户
1 | drop user user@"%"; |
快速到出大量数据
一、导出数据
1、mysqldump
2、重命名压缩
3、scp传输
1 | scp msn.sql.zip root@172.105.xx.xx:/root/ |
二、导入数据
1、解压
1 | unzip msn.sql.zip |
2、连接数据库
1 | mysql -umsn_block -p password |
3、设置参数
1 | #设置参数 |
单机备份
mybackup.conf
1 | username=数据库用户名 |
myback.sh
1 | #/usr/bin/env bash |
异地备份
remote_backup.sh
1 | #!bin/bash |
binlog日志
1、显示mysqlbinlog日志是否开启,以及存储位置
1 | show variables like 'log_%'; |
2、查看所有binlog日志列表
1 | mysql> show master logs; |
3、查看master状态,即最后(最新)一个binlog日志的编号名称,及其最后一个操作事件pos结束点(Position)值
1 | mysql> show master status; |
4、刷新log日志,自此刻开始产生一个新编号的binlog日志文件
1 | mysql> flush logs; |
注:每当mysqld服务重启时,会自动执行此命令,刷新binlog日志;在mysqldump备份数据时加 -F 选项也会刷新binlog日志;
5、重置(清空)所有binlog日志
此命令切勿随便执行。
1 | mysql> reset master; |