深入浅出MySQL第三版、MySQL排错指南、高性能MySQL
原理类
《数据库系统概念 原书第六版》、《数据库系统实现/概念》、《数据库与 事务处理》、《数据库索引设计与优化》、《事务处理 概念与技术》
操作运维、源码类
《MySQL 官方文档》、《MySQL 技术内幕 第 5 版》、《深入理解 MySQL》、 《深入理解 MySQL 核心技术》、《MySQL 性能调优与架构设计》、《高可用 MySQL —构建健壮的数据中心》、《MySQL技术内幕 : InnoDB 存储引擎 第2版》、 《数据库查询优化器的艺术》和《MySQL运维内参》、《高性能 MySQL》、PYTHON(PERL)、Linux运维和脚本编写等
1、简单的MySql权限
1.1、root用户登录mysql服务,执行
mysql -uroot -proot
grant all privileges on . TO ‘root’@’%’ IDENTIFIED BY ‘root’ WITH GRANT OPTION;
flush privileges;
1.2、使用root 用户,执行
grant SELECT on mall.* TO ‘dev’@‘192.168.163.%’ IDENTIFIED BY ‘123’ WITH GRANT OPTION;
很简单的一句 sql,创建了一个 dev 的用户,密码为 123,仅仅运行在网段为 192.168.163.的网段进行查询操作
再执行一条命令
show grants for ‘dev’@‘192.168.163.%’
2、深入研究下MySql权限
2.1、用户标识
mysql中的权限不是单纯的赋予给用户的,而是赋予给”用户+IP”的
‘dev’@‘192.168.0.168’ 、 ‘dev’@‘127.0.0.1’ 与 ‘dev’@‘localhost’ 这3个是完全不同的用户标识(哪怕你本机的ip就是192.168.0.168)
2.2、用户权限所涉及的表
mysql.user User的一行记录代表一个用户标识
mysql.db db的一行记录代表对数据库的权限
mysql.tables_priv tables_priv 的一行记录代表对表的权限
mysql.columns_priv columns_priv 的一行记录代表对某一列的权限
2.3、示例
有张account表
前面创建的dev用户我不想让他访问balance列,id和name列是可以访问的
分别查看tables_priv,columns_priv表的数据
REVOKE SELECT on mall. from ‘dev’@‘192.168.163.%’
使用dev登陆查询
select * from account
select id,name from account
2.4、mysql的角色
2.4.1、准备工作
mysql5.7开始才正式支持角色功能,而且连mysql官方把它叫做“Role Like”(不是角色像角色)
show variables like “%proxy%”
得先把check_proxy_users,mysql_native_password_proxy_users 这两个变量设置成true才行
set GLOBAL check_proxy_users =1;
set GLOBAL mysql_native_password_proxy_users = 1;
也可以把这两个配置设置到 my.cnf 中
2.4.2、创建一个角色
create USER ‘dev_role’
这里创建得是个user,为了像角色一点,给这user取名叫dev_role,为了方便没用使用密码
2.4.3、创建2个人员账号
这两个用户也没设置密码
2.4.4、两个用户加到组
后台执行
GRANT PROXY ON ‘’@’’ TO ‘root’@’%’ WITH GRANT OPTION;
grant proxy on ‘dev_role’ to ‘zhangsan’
grant proxy on ‘dev_role’ to ‘lisi’
查看其中一个用户的权限
show grants for ‘lisi’
2.4.5、给角色dev_role权限
grant select(id,name) on mall.account to ‘dev_role’
2.4.6、测试
lisi登录系统进行查询
1. int类型
类型 | 字节 | 最小值 | 最大值 |
---|---|---|---|
(带符号的/无符号的) | (带符号的/无符号的) | ||
TINYINT | 1 | -128 | 127 |
0 | 255 | ||
SMALLINT | 2 | -32768 | 32767 |
0 | 65535 | ||
MEDIUMINT | 3 | -8388608 | 8388607 |
0 | 16777215 | ||
INT | 4 | -2147483648 | 2147483647 |
0 | 4294967295 | ||
BIGINT | 8 | -9223372036854775808 | 9223372036854775807 |
0 | 18446744073709551615 |
2. 有无符号
在项目中使用INT,而且是有符号的
create table test_unsigned(a int unsigned, b int unsigned);
insert into test_unsigned values(1, 2);
select b - a from test_unsigned;
select a - b from test_unsigned; --运行出错
3. INT(N)
create table test_int_n(a int(4) zerofill);
insert into test_int_n values(1);
insert into test_int_n values(123456);
int(N)中的N是显示宽度, 不表示存储的数字的长度的上限。
zerofill 表示当存储的数字长度 < N 时,用 数字0填充左边,直至补满长度N 当存储数字的长度超过N时 ,按照实际存储的数字显示
4. 自动增长
类型 | 说明 | N 的含义 | 是否有字符集 | 最大长度 |
---|---|---|---|---|
CHAR(N) | 定长字符 | 字符 | 是 | 255 |
VARCHAR(N) | 变长字符 | 字符 | 是 | 16384 |
BINARY(N) | 定长二进制字节 | 字节 | 否 | 255 |
VARBINARY(N) | 变长二进制字节 | 字节 | 否 | 16384 |
TINYBLOB(N) | 二进制大对象 | 字节 | 否 | 256 |
BLOB(N) | 二进制大对象 | 字节 | 否 | 16K |
MEDIUMBLOB(N) | 二进制大对象 | 字节 | 否 | 16M |
LONGBLOB(N) | 二进制大对象 | 字节 | 否 | 4G |
TINYTEXT(N) | 大对象 | 字节 | 是 | 256 |
TEXT(N) | 大对象 | 字节 | 是 | 16K |
MEDIUMTEXT(N) | 大对象 | 字节 | 是 | 16M |
LONGTEXT(N) | 大对象 | 字节 | 是 | 4G |
6. 时间类型
日期类型 | 占用空间 | 表示范围 |
---|---|---|
DATETIME | 8 | 1000-01-01 00:00:00 ~ 9999-12-31 23:59:59 |
DATE | 3 | 1000-01-01 ~ 9999-12-31 |
TIMESTAMP | 4 | 1970-01-01 00:00:00UTC ~ 2038-01-19 03:14:07UTC |
YEAR | 1 | YEAR(2):1970-2070, YEAR(4):1901-2155 |
TIME | 3 | -838:59:59 ~ 838:59:59 |
datatime与timestamp区别
7. JSON类型
1、JSON数据准备
2、JSON函数
2.1、json_extract抽取
2.2、JSON_OBJECT将对象转为json
insert into json_data values ( null, json_object(“name”, “zhaoliu”, “email”, “hao123.com”, “age”,30));
2.3、json_insert插入数据
2.4、json_merge 合并数据并返回
2.5、其他函数
https://dev.mysql.com/doc/refman/5.7/en/json-function-reference.html
1、体系
2、连接层
当MySQL启动(MySQL服务器就是一个进程),等待客户端连接,每一个客户端连接请求, 服务器都会新建一个线程处理(如果是线程池的话,则是分配一个空闲的线程),每个线程独立,拥有各自的内存处理空间
show VARIABLES like ‘%max_connections%’
连接到服务器,服务器需要对其进行验证,也就是用户名、IP、密码验证,一旦连接成功, 还要验证是否具有执行某个特定查询的权限(例如,是否允许客户端对某个数据库某个表的 某个操作)
3、SQL处理层
这一层主要功能有:SQL 语句的解析、优化,缓存的查询,MySQL 内置函数的实现,跨存储 引擎功能(所谓跨存储引擎就是说每个引擎都需提供的功能(引擎需对外提供接口)),例 如:存储过程、触发器、视图等。
4、缓存
show variables like ‘%query_cache_type%’ – 默认不开启
show variables like ‘%query_cache_size%’ --默认值 1M
SET GLOBAL query_cache_type = 1; --会报错
query_cache_type 只能配置在 my.cnf 文件中,这大大限制了QC的作用
在生产环境建议不开启,除非经常有sql完全一模一样的查询
QC要求严格 2次SQL请求要完全一样,包括SQL语句,连接的数据库、协议版本、字符集等因素都会影响
5、查询解析
6、优化
sql 解析器会通过优化器来优化开发人员写的sql
7、数据库存放位置
show VARIABLES like ‘datadir’;
8、创建一个数据库后,会在上面的 datadir 目录新建一个子文件夹
9、表文件
用户建立的表都会在上面的目录中,它和具体的存储引擎相关,但有个共同的就是都有个 frm 文件,它存放的是表的数据格式
看你的mysql现在已提供什么存储引擎
show engines;
看你的mysql当前默认的存储引擎
show variables like ‘%storage_engine%’;
1、MyISAM
MySql5.5之前默认的存储引擎
MyISAM存储引擎由MYD和MYI组成
表压缩
myisampack -b -f /usr/local/mysql/data/mall/testmysam.MYI
压缩后再往表里面新增数据就新增不了
压缩后,需要
myisamchk -r -f /usr/local/mysql/data/mall/testmysam.MYI
适用场景
非事务型应用(数据仓库,报表,日志数据)
只读类应用
空间类应用(空间函数,坐标)
2、Innodb
Innodb是一种事务性存储引擎
完全支持事务得 ACID 特性
Redo Log和Undo Log
Innodb 支持行级锁(并发程度更高)
对比项 | MyISAM | InnoDB |
---|---|---|
主外键 | 不支持 | 支持 |
事务 | 不支持 | 支持 |
行表锁 | 表锁,即使操作一条记录也会锁住整个表,不适合高并发操作 | 行锁,操作时只锁某一行,不对其他行有影响,适合高并发操作 |
缓存 | 只缓存索引,不缓存真实数据 | 不仅缓存索引还要缓存真实数据,对内存要求较高,而且内存大小对性能有决定性影响 |
show VARIABLES like ‘innodb_log_buffer_size’
3、CSV
以csv格式进行数据存储
所有列都不能为null
不支持索引(不适合大表,不适合在线处理)
可以对数据文件直接编辑(保存文本文件内容)
create table mycsv(id int not null,c1 VARCHAR(10) not null,c2 char(10) not null) engine=csv;
insert into mycsv values(1,‘aaa’,‘bbb’),(2,‘cccc’,‘dddd’);
vi /usr/local/mysql/data/mall/mycsv.CSV 修改文本数据
flush TABLES;
select * from mycsv
create index idx_id on mycsv(id)
4、Archive
以zlib对表数据进行压缩,磁盘I/O更少
数据存储在ARZ为后缀的文件中
只支持insert和select 操作
只允许在自增ID列上加索引
5、Memory
特点
文件系统存储特点,也称HEAP存储引擎,所以数据保存在内存中
支持HASH索引和BTree索引
所有字段都是固定长度varchar(10) = char(10)
不支持Blog和Text等大字段
Memory存储引擎使用表级锁
最大大小由max_heap_table_size参数决定
show VARIABLES like ‘max_heap_table_size’;
create table mymemory(id int,c1 varchar(10),c2 char(10),c3 text) engine = memory;
create table mymemory(id int,c1 varchar(10),c2 char(10)) engine = memory;
create index idx_c1 on mymemory(c1);
create index idx_c2 using btree on mymemory(c2);
show index from mymemory;
show TABLE status LIKE ‘mymemory’;
与临时表的区别
使用场景
hash 索引用于查找或者是映射表(邮编和地区的对应表)
用于保存数据分析中产生的中间表
用于缓存周期性聚合数据的结果表
6、Ferderated
特点
提供了访问远程 MySQL 服务器上表的方法
本地不存储数据,数据全部放到远程服务器上
本地需要保存表结构和远程服务器的连接信息
配置
默认禁止,启用需要再启动时增加 federated 参数
show ENGINES
create database local;
create database remote;
create table remote_fed(id int auto_increment not null,c1 varchar(10) not null default ‘’,c2 char(10) not null default ‘’,primary key(id)) engine = INNODB
INSERT into remote_fed(c1,c2) values(‘aaa’,‘bbb’),(‘ccc’,‘ddd’),(‘eee’,‘fff’); CREATE TABLE local_fed
( id
int(11) NOT NULL AUTO_INCREMENT, c1
varchar(10) NOT NULL DEFAULT ‘’, c2
char(10) NOT NULL DEFAULT ‘’, PRIMARY KEY (id
) ) ENGINE=federated CONNECTION =‘mysql://root:root%@127.0.0.1:3306/remote/remote_fed’
select * from local_fed
delete from local_fed where id = 2
select * from remote.remote_fed
1、bin目录
在MySQL的安装目录下有一个特别特别重要的bin目录,这个目录下存放着 许多可执行文件。
1.1、启动MySQL服务器程序
在类UNIX系统中用来启动MySQL服务器程序的可执行文件有很多,大多在 MySQL安装目录的bin目录下。
A、mysqld
mysqld这个可执行文件就代表着MySQL服务器程序,运行这个可执行文件 就可以直接启动一个服务器进程。但这个命令不常用。
B、mysqld_safe
mysqld_safe是一个启动脚本,它会间接的调用mysqld,而且还顺便启动了 另外一个监控进程,这个监控进程在服务器进程挂了的时候,可以帮助重启它。 另外,使用mysqld_safe 启动服务器程序时,它会将服务器程序的出错信息和其他诊断信息重定向到某个文件中,产生出错日志,这样可以方便我们找出发生错误的原因。
C、mysql.server
mysql.server 也是一个启动脚本,它会间接的调用mysqld_safe,在调用 mysql.server 时在后边指定start参数就可以启动服务器程序了
就像这样: mysql.server start
需要注意的是,这个mysql.server文件其实是一个链接文件,它的实际文件 是support-files/mysql.server,所以如果在bin目录找不到,到 support-files 下去找找,而且如果你愿意的话,自行用ln命令在bin创建一个链接。
另外,我们还可以使用mysql.server 命令来关闭正在运行的服务器程序,只 要把start参数换成stop就好了:
mysql.server stop
D、mysqld_multi
其实我们一台计算机上也可以运行多个服务器实例,也就是运行多个MySQL服务器进程。mysql_multi 可执行文件可以对每一个服务器进程的启动或停止进行监控。
1.2、客户端程序
在我们成功启动MySQL服务器程序后,就可以接着启动客户端程序来连接到 这个服务器了,bin目录下有许多客户端程序,比方说mysqladmin、mysqldump、mysqlcheck 等等。
我们常用的是可执行文件mysql,通过这个可执行文件可以让我们和服务器 程序进程交互,也就是发送请求,接收服务器的处理结果。
mysqladmin 执行管理操作的工具,检查服务器配置、当前运行状态,创建、 删除数据库、设置新密码。
mysqldump 数据库逻辑备份程序。
mysqlbackup 备份数据表、整个数据库、所有数据库,一般来说 mysqldump 备份、mysql 还原。
2、启动选项和参数
2.1、配置参数文件
当MySQL实例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各种文件所在位置以及指定某些初始化参数,这些参数通常定义了某种内存结构有多大等。在默认情况下,MySQL实例会按照一定的顺序在指定的位置进行读取,用户只需通过命令mysql --help|grep my.cnf 来寻找即可。
当然,也可以在启动MySQL时,指定配置文件:
这个时候,就会以启动时指定的配置文件为准。
MySQL数据库的参数文件是以文本方式进行存储的。可以直接通过一些常用 的文本编辑软件进行参数的修改
2.2、参数的查看和修改
可以通过命令show variables查看数据库中的所有参数,也可以通过LIKE来 过滤参数名,前面查找数据库引擎时已经展示过了。从MySQL5.1版本开始,还可以通过information_schema架构下的GLOBAL_VARIABLES视图来进行查找,推荐使用命令show variables,使用更为简单,且各版本的 MySQL数据库都支持。
参数的具体含义可以参考 MySQL 官方手册: https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html
MySQL数据库中的参数可以分为两类:动态(dynamic)参数和静态(static)参 数。同时从作用范围又可以分为全局变量和会话变量。
动态参数意味着可以在MySQL实例运行中进行更改,静态参数说明在整个实例生命周期内都不得进行更改,就好像是只读(read only)的。
全局变量(GLOBAL)影响服务器的整体操作。
会话变量(SESSION/LOCAL)影响某个客户端连接的操作。
举个例子,用default_storage_engine来说明,在服务器启动时会初始化一 个名为default_storage_engine,作用范围为GLOBAL的系统变量。之后每当有一 个客户端连接到该服务器时,服务器都会单独为该客户端分配一个名为 default_storage_engine,作用范围为SESSION的系统变量,该作用范围为 SESSION的系统变量值按照当前作用范围为GLOBAL的同名系统变量值进行初始化。
可以通过SET命令对动态的参数值进行修改。
SET的语法如下:
SET
l [global l session ] system_var_name= expr
l [ @@global.l @@session.] system_var_name= expr
比如:
SET read_ buffer_size=524288;
SET @@global.read_ buffer_size=524288;
MySQL所有动态变量的可修改范围,可以参考MySQL官方手册的 Dynamic System Variables的相关内容: https://dev.mysql.com/doc/refman/5.7/en/dynamic-system-variables.html
对于静态变量,若对其进行修改,会得到类似如下错误:
3、数据目录
3.1、MySQL中的数据目录
数据目录对应着一个系统变量datadir,我们在使用客户端与服务器建立连接之后查看这个系统变量的值就可以了,当然这个目录可以通过配置文件进行修改,由我们自己进行指定。
show variables like ‘datadir’;
3.2、数据目录中放些什么
MySOL在运行过程中都会产生哪些数据呢?当然会包含我们创建的数据库、 表、视图和触发器等用户数据,除了这些用户数据,为了程序更好的运行,MySQL也会创建一些其他的额外数据
数据库在文件系统中的表示
每个数据库都对应数据目录下的一个子目录, 或者说对应一个文件夹,我们每当我们新建一个数据库时,MySQL会帮我们做这两件事儿:
A、在数据目录下创建一个和数据库名同名的子目录(或者说是文件夹)。
B、在与数据库名同名的子目录下创建一个名为db.opt的文件,这个文件中包含了该数据库的各种属性,比方说该数据库的字符集和比较规则是什么
表在文件系统中的表示
我们的数据其实都是以记录的形式插入到表中的,每个表的信息其实可以分 为两种:
1、表结构的定义
2、表中的数据
表结构就是定义该表的名称,表中有多少列,每个列的数据类型,约束条件和索引,字符集和比较规则等各种信息,这些信息都体现在了建表语句中了。为了保存这些信息,InnoDB和MyIASM存储引擎都在数据目录下对应的数据库子目录下创建了一个专门用于描述表结构的文件, 文件名为:表名.frm
并以二进制格式存储
lnnoDB如何存储表数据
InnoDB的数据会放在一个表空间或者文件空间(英文名: table space或者file space),这个表空间是一个抽象的概念,它可以对应文件系统上一个或多个真实文件(不同表空间对应的文件数量可能不同)。每一个表空间可以被划分 为很多很多很多个页,我们的表数据就存放在某个表空间下的某些页里。表空间有好几种类型。
系统表空间(system tablespace)
系统表空间可以对应文件系统上一个或多个实际的文件,默认情况下,InnoDB会在数据目录下创建一个名为ibdata1、大小为12M的文件,这个文件就是对应的系统表空间在文件系统上的表示。
这个文件是自扩展文件,也就是当不够用的时候它会自己增加文件大小,如果你想让系统表空间对应文件系统上多个实际文件,或者仅仅觉得原来的 ibdata1这个文件名难听,那可以在MySQL启动时配置对应的文件路径以及它们的大小,也可以把系统表空间对应的文件路径不配置到数据目录下, 甚至可以配置到单独的磁盘分区上。
需要注意的一点是,在一个MySQL服务器中,系统表空间只有一份。从 MySQL5.5.7到MySQL5.6.6之间的各个版本中,我们表中的数据都会被默认存储到这个系统表空间。
独立表空间(file-per-table tablespace)
在MySQL5.6.6以及之后的版本中,InnoB并不会默认的把各个表的数据存储 到系统表空间中,而是为每一个表建立一个独立表空间,也就是说我们创建了多少个表,就有多少个独立表空间。使用独立表空间来存储表数据的话,会在该表所属数据库对应的子目录下创建一个表示该独立表空间的文件,文件名和表名相同,只不过添加了一个.ibd 的扩展名而已,所以完整的文件名称长这样:表名.ibd。
account.ibd文件就用来存储account表中的数据和索引。当然我们也可以自己 指定使用系统表空间还是独立表空间来存储数据,这个功能由启动参数 innodb_file_per_table控制,比如说我们想刻意将表数据都存储到系统表空 间时,可以在启动MySQL服务器的时候这样配置:
[server]
innodb_file_per_table=0
当innodb_file_per_table的值为0时,代表使用系统表空间;
当innodb_file_per_table的值为1时,代表使用独立表空间。
不过innodb_file_per_table参数只对新建的表起作用,对于已经分配了表空间的表并不起作用。
其他类型表空间
随着MySQL的发展,除了上述两种老牌表空间之外,现在还新提出了一些不同类型的表空间,比如通用表空间(general tablespace) ,undo表空间 (undotablespace)、临时表空间(temporary tablespace)等。
MyISAM如何存储表数据
在MyISAM中的数据和索引是分开存放的。所以在文件系统中也是使用不同 的文件来存储数据文件和索引文件。而且和InnoDB不同的是,MyISAM并没有表空间一说,表数据都存放到对应的数据库子目录下。
testmysam表使用MyISAM存储引擎的话,那么在它所在数据库对应的数据目录下会为testmysam表创建三个文件:
testmysam.MYD 代表表的数据文件,也就是插入的用户记录;testmysam.MYI代表表的索引文件,为该表创建的索引都会放到这个文件中
4、日志文件
常见的日志文件有:错误日志(error log)、慢查询日志(slow query log)、 查询日志(query log)、二进制文件(bin log)、redo日志、undo日志。
错误日志
错误日志文件对MySQL的启动、运行、关闭过程进行了记录。遇到问题时应该首先查看该文件以便定位问题。该文件不仅记录了所有的错误信息,也记录一些警告信息或正确的信息
用户可以通过下面命令来查看错误日志文件的位置:
show variables like ‘log_error’\G;
当MySQL不能正常启动时,第一个必须查找的文件应该就是错误日志文件, 该文件记录了错误信息。
慢查询日志
慢查询日志可以帮助定位可能存在问题的SQL语句,从而进行SQL语句层面 的优化
查询日志
查询日志记录了所有对MySQL数据库请求的信息,无论这些请求是否得到了正确的执行。
默认文件名:主机名.log
二进制日志(binlog)
二进制日志记录了对MySQL数据库执行更改的所有操作,若操作本身没有导致数据库发生变化,该操作可能也会写入二进制文件。但是不包括select和 show这类操作(因为这些操作对数据本身不会进行修改)
二进制日志的几种作用:
恢复(recovery):某些数据的恢复需要二进制日志,例如,在一个数据库全备文件恢复后,用户可以通过二进制文件进行point-in-time的恢复
复制(replication):其原理与恢复类似,通过复制和执行二进制日志使一台远程的MySQL数据库(一般称为 slave 或 standby)与一台MySQL数据库(一般称为master或primary)进行实时同步
审计(audit):用户可以通过二进制日志中的信息来进行审计,判断是否有对数据库进行注入的攻击
log-bin参数
该参数用来控制是否开启二进制日志,默认为关闭
如果想要开启二进制日志的功能,可以在MySQL的配置文件中指定如下的格式:
“name”为二进制日志文件的名称
如果不提供name,那么数据库会使用默认的日志文件名(文件名为主机名, 后缀名为二进制日志的序列号),且文件保存在数据库所在的目录(datadir下)
–启用/设置二进制日志文件(name可省略)
log-bin=name;
配置以后,就会在数据目录下产生类似于:
bin_log.00001即为二进制日志文件;bin_log.index为二进制的索引文件,用 来存储过往产生的二进制日志序号,通常情况下,不建议手动修改这个文件。
二进制日志文件在默认情况下并没有启动,需要手动指定参数来启动。开启 这个选项会对MySQL的性能造成影响,但是性能损失十分有限。根据MySQL官方手册中的测试指明,开启二进制日志会使性能下降1%。
5、其他数据文件
除了我们上边说的这些用户自己存储的数据以外,数据文件下还包括为了更 好运行程序的一些额外文件,当然这些文件不一定会放在数据目录下,而且可以在配置文件或者启动时另外指定存放目录。
主要包括这几种类型的文件:
服务器进程文件
我们知道每运行一个MySQL服务器程序,都意味着启动一个进程。MySQL 服务器会把自己的进程ID写入到一个pid文件中。
socket文件
当用UNIX域套接字方式进行连接时需要的文件。
默认/自动生成的SSL和RSA证书和密钥文件
1、系统库简介
MySQL有几个系统数据库,这几个数据库包含了MySQL服务器运行过程中 所需的一些信息以及一些运行状态信息
performance_schema
这个数据库里主要保存MySQL服务器运行过程中的一些状态信息,算是对 MySQL服务器的一个性能监控。包括统计最近执行了哪些语句,在执行过程的每个阶段都花费了多长时间,内存的使用情况等等信息。
information_schema
这个数据库保存着MySQL服务器维护的所有其他数据库的信息,比如有哪些表、哪些视图、哪些触发器、哪些列、哪些索引。这些信息并不是真实的用户数据,而是一些描述性信息,有时候也称之为元数据。
sys
这个数据库主要是通过视图的形式把information_schema和 performance_schema结合起来,让程序员可以更方便的了解MySQL服务器的一 些性能信息。
mysql
这个数据库核心,它存储了MySQL的用户账户和权限信息,一些存储过程、 事件的定义信息,一些运行过程中产生的日志信息,一些帮助信息以及时区信息等。
2、performance_schema
2.1、performance_schema定义
MySQL的performance_schema是运行在较低级别的用于监控MySQL Server运行过程中的资源消耗、资源等待等情况的一个功能特性,它具有以下特点:
• performance_schema提供了一种在数据库运行时实时检查Server内部执行情况的方法。performance_schema数据库中的表使用performance_schema存储引擎。该数据库主要关注数据库运行过程中的性能相关数据。
• performance_schema通过监视Server的事件来实现监视其内部执行情况, “事件”就是在Server内部活动中所做的任何事情以及对应的时间消耗,利用这 些信息来判断Server中的相关资源被消耗在哪里。一般来说,事件可以是函数调用、操作系统的等待、SQL语句执行的阶段[如SQL语句执行过程中的 parsing(解析)或sorting(排序)阶段]或者整个SQL语句的集合。采集事件可以方便地提供Server中的相关存储引擎对磁盘文件、表 I/O、表锁等资源的同步调用信息。
• 当前活跃事件、历史事件和事件摘要相关表中记录的信息,能提供某个事件的执行次数、使用时长,进而可用于分析与某个特定线程、特定对象(如mutex或file)相关联的活动。
• performance_schema存储引擎使用Server源代码中的“检测点”来实现事件数据的收集。对于performance_schema实现机制本身的代码没有相关的单 独线程来检测,这与其他功能(如复制或事件计划程序)不同。
收集到的事件数据被存储在performance_schema数据库的表中。对于这些 表可以使用SELECT语句查询,也可以使用SQL语句更新performance_schema数据库中的表记录(比如动态修改 performance_schema的以“setup_”开头的配置表,但要注意,配置表的更改会立即生效,这会影响数据收集)。
• performance_schema的表中数据不会持久化存储在磁盘中,而是保存在内存中,一旦服务器重启,这些数据就会丢失(包括配置表在内的整个 performance_schema下的所有数据)。
2.2、performance_schema使用
检查当前数据库版本是否支持
performance_schema被视为存储引擎,如果该引擎可用,则应该在 INFORMATION_SCHEMA.ENGINES表或show engines语句的输出中可以看到它的Support字段值为YES,如下所示:
当我们看到performance_schema对应的Support字段值为YES时,就表示当 前的数据库版本是支持performance_schema的。但确认了数据库实例支持 performance_schema存储引擎就可以使用了吗?NO,很遗憾, performance_schema在MySQL 5.6及之前的版本中默认没有启用,在 MySQL5.7及之后的版本中才修改为默认启用。
启用performance_schema
如果要显式启用或关闭performance_schema,则需要使用参数performance_schema=ON|OFF来设置,并在my.cnf中进行配置。注意:该参数为只读参数,需要在实例启动之前设置才生效
mysqld启动之后,通过如下语句查看performance_schema启用是否生效(值 为ON表示performance_schema已初始化成功且可以使用了;值为OFF表示在启用performance_schema时发生某些错误,可以查看错误日志进行排查)。
可以通过查询INFORMATION_SCHEMA.TABLES表中与performance_schema存储引擎相关的元数据,或者在performance_schema库下使用show tables语句来了解其存在哪些表。
performance_schema表的分类
performance_schema库下的表可以按照监视的不同维度进行分组,例如: 按照不同的数据库对象进行分组、按照不同的事件类型进行分组,或者按照事件类型分组之后,再进一步按照账号、主机、程序、线程、用户等进行细分。 下面介绍按照事件类型分组记录性能事件数据的表。
• 语句事件记录表:记录语句事件信息的表,包括:
events_statements_current(当前语句事件表)、events_statements_history(历史语句事件表)、events_statements_history_long(长语句历史事件表)以及一 些summary表(聚合后的摘要表)。其中,summary表还可以根据账号(account)、 主机(host)、程序(program)、线程(thread)、用户(user)和全局(global)再进行细分。
show tables like ‘events_statement%’;
• 等待事件记录表:
show tables like ‘events_wait%’;
• 阶段事件记录表:记录语句执行阶段事件的表
show tables like ‘events_stage%’;
• 事务事件记录表:记录与事务相关的事件的表
show tables like ‘events_transaction%’;
• 监视文件系统层调用的表:
show tables like ‘%file%’;
• 监视内存使用的表:
show tables like ‘%memory%’;
• 动态对performance_schema进行配置的配置表:
show tables like ‘%setup%’;
performance_schema简单配置与使用
当数据库初始化完成并启动时,并非所有的instruments(在采集配置项的配置表中,每一项都有一个开关字段,或为YES,或为NO)和consumers(与采集配置项类似,也有一个对应的事件类型保存表配置项,为YES表示对应的表保存性能数据,为NO表示对应的表不保存性能数据)都启用了,所以默认不会收集所有的事件。
可能你想检测的事件并没有打开,需要进行设置。可以使用如下两条语句打 开对应的instruments和consumers,我们以配置监测等待事件数据为例进行说明。
打开等待事件的采集器配置项开关,需要修改setup_instruments配置表中对应的采集器配置项。
update setup_instruments set enabled=‘yes’,timed=‘yes’ where name like ‘wait%’;
打开等待事件的保存表配置项开关,修改setup_consumers配置表中对应的 配置项。
update setup_consumers set enabled=‘yes’ where name like ‘wait%’;
配置好之后,我们就可以查看Server当前正在做什么了。可以通过查询events_waits_current表来得知,该表中每个线程只包含一行数据,用于显示每个线程的最新监视事件(正在做的事情)。
_current表中每个线程只保留一条记录,且一旦线程完成工作,该表中就不会再记录该线程的事件信息了。history表中记录每个线程已经执行完成的事件信息,但每个线程的事件信息只记录10条,再多就会被覆盖掉。*history_long表中记录所有线程的事件信息,但总记录数量是10000行,超过会被覆盖掉。
summary表提供所有事件的汇总信息。该组中的表以不同的方式汇总事件数 据(如:按用户、按主机、按线程等汇总)。
查看最近执行失败的SQL语句
在performance_schema的语句事件记录表中针对每一条语句的执行状态都记录了较为详细的信息,例如:events_statements_表和 events_statements_summary_by_digest表(events_statements_表记录了语句所有的执行错误信息,而events_statements_summary_by_digest表只记录了语句在执行过程中发生错误的语句记录统计信息,不记录具体的错误类型,例如:不记录语法错误类的信息)。下面看看如何使用这两个表查询语句发生错误的语句信息。
首先,我们模拟一条语法错误的SQL语句,使用events_statements_history_long表或者events_statements_history表查询发生语法错误的SQL语句:
然后,查询events_statements_history表中错误号为1064的记录
select * from events_statements_history where mysql_errno=1064\G
不知道错误号是多少,可以查询发生错误次数不为0的语句记录,在里边找 到SQL_TEXT和MESSAGE_TEXT字段(提示信息为语法错误的就是它)。
查看最近的事务执行信息
可以借助performance_schema的events_transactions*表来查看与事务相关的记录,在这些表中详细记录了是否有事务被回滚、活跃(长时间未提交的事务也属于活跃事务)或已提交等信息。 首先需要进行配置启用,事务事件默认并未启用
update setup_instruments set enabled=‘yes’,timed=‘yes’ where name like ‘transaction%’;
update setup_consumers set enabled=‘yes’ where name like ‘%transaction%’;
开启一个新会话(会话 2)用于执行事务,并模拟事务回滚
查询活跃事务,活跃事务表示当前正在执行的事务事件,需要从events_transactions_current表中查询
会话2中回滚事务:
查询事务事件当前表和事务事件历史记录表,可以看到在两表中都记录了一 行事务事件信息,线程ID为49的线程执行了一个事务,事务状态为ROLLED BACK。
但是当我们关闭会话 2 以后,事务事件当前表中的记录就消失了
3、information_schema
3.1、information_schema定义
information_schema提供了对数据库元数据、统计信息以及有关MySQL Server信息的访问(例如:数据库名或表名、字段的数据类型和访问权限等)。 该库中保存的信息也可以称为 MySQL 的数据字典或系统目录。
在每个MySQL实例中都有一个独立的information_schema,用来存储MySQL 实例中所有其他数据库的基本信息。information_schema库下包含多个只读表(非持久表),所以在磁盘中的数据目录下没有对应的关联文件,且不能对这些表设置触发器。虽然在查询时可以使用USE语句将默认数据库设置为 information_schema,但该库下的所有表是只读的,不能执行INSERT、UPDATE、 DELETE等数据变更操作。
针对information_schema下的表的查询操作可以替代一些SHOW查询语句(例如:SHOW DATABASES、SHOW TABLES 等)。
information_schema下的所有表使用的都是Memory和InnoDB存储引擎, 且都是临时表,不是持久表,在数据库重启之后这些数据会丢失。在MySQL的 4个系统库中,information_schema也是唯一一个在文件系统上没有对应库表的目录和文件的系统库。
3.2、information_schema表分类
Server层的统计信息字典表
(1) COLUMNS
• 提供查询表中的列(字段)信息。
(2) KEY_COLUMN_USAGE
• 提供查询哪些索引列存在约束条件。
• 该表中的信息包含主键、唯一索引、外键等约束信息,例如:所在的库表列名、引用的库表列名等。该表中的信息与TABLE_CONSTRAINTS表中记录的信息有些类似,但TABLE_CONSTRAINTS表中没有记录约束引用的库表列信息,而KEY_COLUMN_USAGE表中却记录了TABLE_CONSTRAINTS 表中所没有的约束类型。
(3) REFERENTIAL_CONSTRAINTS
• 提供查询关于外键约束的一些信息。
(4) STATISTICS
• 提供查询关于索引的一些统计信息,一个索引对应一行记录。
(5) TABLE_CONSTRAINTS
• 提供查询与表相关的约束信息。
(6) FILES
• 提供查询与 MySQL 的数据表空间文件相关的信息。
(7) ENGINES
• 提供查询 MySQL Server支持的引擎相关信息。
(8) TABLESPACES
• 提供查询关于活跃表空间的相关信息(主要记录的是NDB存储引擎的表空间信息)。
• 注意:该表不提供有关InnoDB存储引擎的表空间信息。对于InnoDB表空间的元数据信息,请查询INNODB_SYS_TABLESPACES表和INNODB_SYS_DATAFILES表。另外,从MySQL 5.7.8开始,INFORMATION_SCHEMA.FILES表也提供查询InnoDB表空间的元数据信息。
(9) SCHEMATA
• 提供查询MySQL Server中的数据库列表信息,一个schema就代表一个数据库。
Server层的表级别对象字典表
(1) VIEWS
• 提供查询数据库中的视图相关信息。查询该表的账户需要拥有show view权限。
(2) TRIGGERS
• 提供查询关于某个数据库下的触发器相关信息。
(3) TABLES
• 提供查询与数据库内的表相关的基本信息。
(4) ROUTINES
• 提供查询关于存储过程和存储函数的信息(不包括用户自定义函数)。 该表中的信息与mysql.proc中记录的信息相对应(如果该表中有值的话)。
(5) PARTITIONS
• 提供查询关于分区表的信息。
(6) EVENTS
• 提供查询与计划任务事件相关的信息。
(7) PARAMETERS
• 提供有关存储过程和函数的参数信息,以及有关存储函数的返回值信息。 这些参数信息与mysql.proc表中的param_list列记录的内容类似。
Server层的混杂信息字典表
(1) GLOBAL_STATUS、GLOBAL_VARIABLES、SESSION_STATUS、 SESSION_VARIABLES
• 提供查询全局、会话级别的状态变量与系统变量信息。
(2) OPTIMIZER_TRACE
• 提供优化程序跟踪功能产生的信息。
• 跟踪功能默认是关闭的,使用optimizer_trace系统变量启用跟踪功能。 如果开启该功能,则每个会话只能跟踪它自己执行的语句,不能看到其他会话执行的语句,且每个会话只能记录最后一条跟踪的SQL语句。
(3) PLUGINS
• 提供查询关于MySQL Server支持哪些插件的信息。
(4) PROCESSLIST
• 提供查询一些关于线程运行过程中的状态信息。
(5) PROFILING
• 提供查询关于语句性能分析的信息。其记录内容对应于SHOW PROFILES和SHOW PROFILE语句产生的信息。该表只有在会话变量profiling=1时才会记录语句性能分析信息,否则该表不记录。
• 注意:从MySQL5.7.2开始,此表不再推荐使用,在未来的MySQL版本中删除,改用Performance Schema代替。
(6) CHARACTER_SETS
• 提供查询MySQL Server 的可用字符集。
(7)COLLATIONS
• 提供查询MySQL Server支持的可用校对规则。
(8)COLLATION_CHARACTER_SET_APPLICABILITY
• 提供查询MySQL Server中哪种字符集适用于什么校对规则。查询结果集相当于从SHOW COLLATION获得的结果集的前两个字段值。目前并没有发现该表有太大的作用。
(9)COLUMN_PRIVILEGES
• 提供查询关于列(字段)的权限信息,表中的内容来自mysql.column_priv列权限表(需要针对一个表的列单独授权之后才会有内容)。
(10)SCHEMA_PRIVILEGES
• 提供查询关于库级别的权限信息,每种类型的库级别权限记录一行信息, 该表中的信息来自mysql.db表。
(11)TABLE_PRIVILEGES
• 提供查询关于表级别的权限信息,该表中的内容来自mysql.tables_priv表。
(12)USER_PRIVILEGES
• 提供查询全局权限的信息,该表中的信息来自mysql.user表。
InnoDB层的系统字典表
(1)INNODB_SYS_DATAFILES
• 提供查询InnoDB所有表空间类型文件的元数据(内部使用的表空间ID和表空间文件的路径信息),包括独立表空间、常规表空间、系统表空间、临时表空间和undo空间(如果开启了独立undo空间的话)。
• 该表中的信息等同于InnoDB数据字典内部SYS_DATAFILES表的信息。 (2)INNODB_SYS_VIRTUAL
• 提供查询有关InnoDB虚拟生成列和与之关联的列的元数据信息,等同于InnoDB数据字典内部SYS_VIRTUAL表的信息。该表中展示的行信息是与虚拟生成列相关联列的每个列的信息。
(3)INNODB_SYS_INDEXES
• 提供查询有关InnoDB索引的元数据信息,等同于InnoDB数据字典内部 SYS_INDEXES表中的信息。
(4)INNODB_SYS_TABLES
• 提供查询有关InnoDB表的元数据信息,等同于InnoDB数据字典内部SYS_TABLES表的信息。
(5)INNODB_SYS_FIELDS
• 提供查询有关InnoDB索引键列(字段)的元数据信息,等同于InnoDB数据字典内部SYS_FIELDS表的信息。
(6)INNODB_SYS_TABLESPACES
• 提供查询有关InnoDB独立表空间和普通表空间的元数据信息(也包含了全文索引表空间),等同于InnoDB数据字典内部SYS_TABLESPACES表的信息。
(7)INNODB_SYS_FOREIGN_COLS
• 提供查询有关InnoDB外键列的状态信息,等同于InnoDB数据字典内部SYS_FOREIGN_COLS表的信息。
(8)INNODB_SYS_COLUMNS
• 提供查询有关 InnoDB 表列的元数据信息,等同于 InnoDB 数据字典内部 SYS_COLUMNS 表的信息。
(9)INNODB_SYS_FOREIGN
• 提供查询有关InnoDB外键的元数据信息,等同于InnoDB数据字典内部SYS_FOREIGN表的信息。
(10)INNODB_SYS_TABLESTATS
• 提供查询有关InnoDB表的较低级别的状态信息视图。 MySQL优化器会使用这些统计信息数据来计算并确定在查询InnoDB表时要使用哪个索引。这些
信息保存在内存中的数据结构中,与存储在磁盘上的数据无对应关系。在InnoDB内部也无对应的系统表。
InnoDB层的锁、事务、统计信息字典表
(1) INNODB_LOCKS
• 提供查询InnoDB引擎中事务正在请求的且同时被其他事务阻塞的锁信息(即没有发生不同事务之间锁等待的锁信息,在这里是查看不到的。例如,当只有一个事务时,无法查看到该事务所加的锁信息)。该表中的内容可用于诊断 高并发下的锁争用信息。
(2)INNODB_TRX
• 提供查询当前在InnoDB引擎中执行的每个事务(不包括只读事务)的信息,包括事务是否正在等待锁、事务什么时间点开始,以及事务正在执行的SQL语句文本信息等(如果有SQL语句的话)。
(3)INNODB_BUFFER_PAGE_LRU
• 提供查询缓冲池中的页面信息。与INNODB_BUFFER_PAGE表不同, INNODB_BUFFER_PAGE_LRU表保存有关InnoDB缓冲池中的页如何进入LRU链表, 以及在缓冲池不够用时确定需要从中逐出哪些页的信息。
(4)INNODB_LOCK_WAITS
• 提供查询InnoDB事务的锁等待信息。如果查询该表为空,则表示无锁等待信息;如果查询该表中有记录,则说明存在锁等待,表中的每一行记录表示一个锁等待关系。在一个锁等待关系中包含:一个等待锁(即,正在请求获得锁) 的事务及其正在等待的锁等信息、一个持有锁(这里指的是发生锁等待事务正在请求的锁)的事务及其所持有的锁等信息。
(5)INNODB_TEMP_TABLE_INFO
• 提供查询有关在InnoDB实例中当前处于活动状态的用户(只对已建立连接的用户有效,断开的用户连接对应的临时表会被自动删除)创建的InnoDB临时表的信息。它不提供查询优化器使用的内部InnoDB临时表的信息。该表在首次查询时创建。
(6)INNODB_BUFFER_PAGE
• 提供查询关于缓冲池中的页相关信息。
(7)INNODB_METRICS
• 提供查询 InnoDB 更为详细的性能信息,是对InnoDB的performance_schema的补充。通过对该表的查询,可用于检查InnoDB的整体健康状况,也可用于诊断性能瓶颈、资源短缺和应用程序的问题等。
(8)INNODB_BUFFER_POOL_STATS
• 提供查询一些InnoDB缓冲池中的状态信息,该表中记录的信息与SHOW ENGINEINNODB STATUS语句输出的缓冲池统计部分信息类似。另外,InnoDB缓冲池的一些状态变量也提供了部分相同的值。
InnoDB层的全文索引字典表
(1)INNODB_FT_CONFIG
(2)INNODB_FT_BEING_DELETED
(3)INNODB_FT_DELETED
(4)INNODB_FT_DEFAULT_STOPWORD
(5)INNODB_FT_INDEX_TABLE
InnoDB层的压缩相关字典表
(1)INNODB_CMP和INNODB_CMP_RESET
• 这两个表中的数据包含了与压缩的InnoDB表页有关的操作状态信息。表中记录的数据为测量数据库中的InnoDB表压缩的有效性提供参考。
(2)INNODB_CMP_PER_INDEX和INNODB_CMP_PER_INDEX_RESET
• 这两个表中记录了与InnoDB压缩表数据和索引相关的操作状态信息,对数据库、表、索引的每个组合使用不同的统计信息,以便为评估特定表的压缩性能和实用性提供参考数据。
(3)INNODB_CMPMEM和INNODB_CMPMEM_RESET
• 这两个表中记录了InnoDB缓冲池中压缩页的状态信息,为测量数据库中InnoDB表压缩的有效性提供参考。
3.3、information_schema应用
查看索引列的信息
INNODB_SYS_FIELDS表提供查询有关InnoDB索引列(字段)的元数据信息, 等同于InnoDB数据字典中SYS_FIELDS表的信息。 INNODB_SYS_INDEXES表提供查询有关InnoDB索引的元数据信息,等同于InnoDB数据字典内部SYS_INDEXES表中的信息。 INNODB_SYS_TABLES表提供查询有关InnoDB表的元数据信息,等同于InnoDB数据字典中SYS_TABLES表的信息。
假设需要查询mall库下的InnoDB表account的索引列名称、组成和 索引列顺序等相关信息
select t.name as d_t_name,i.name as i_name ,i.type as i_type,i.N_FIELDS as i_column_numbers,f.name as i_column_name,f.pos as i_position from INNODB_SYS_TABLES as t join INNODB_SYS_INDEXES as i on t.TABLE_ID=i.TABLE_ID left join INNODB_SYS_FIELDS as f on i.INDEX_ID=f.INDEX_ID where t.name=‘mall/account’;
结果中的列都很好理解,唯一需要解释的是i_type(INNODB_SYS_INDEXES.type),它是表示索引类型的数字ID,0=二级索引、 1=集群索引、2=唯一索引、3=主键索引、32=全文索引、64=空间索引、128=包含虚拟生成列的二级索引。
4、sys系统库
4.1、sys使用须知
sys系统库支持MySQL5.6或更高版本,不支持MySQL5.5.x及以下版本。
因为sys系统库提供了一些代替直接访问performance_schema的视图,所以必须启用performance_schema(将performance_schema系统参数设置为ON), sys 系统库的大部分功能才能正常使用。
同时要完全访问sys系统库,用户必须具有以下数据库的管理员权限。 如果要充分使用sys系统库的功能,则必须启用某些performance_schema的功能。当然sys系统库本身已经提供了启用所有需要的功能的存储过程,比如: 启用所有的wait instruments:
CALL sys.ps_setup_enable_instrument(‘wait’);
启用所有事件类型的current表:
CALL sys.ps_setup_enable_consumer(‘current’);
注意:performance_schema的默认配置就可以满足sys系统库的大部分数据 收集功能。启用所有需要功能会对性能产生一定的影响,因此最好仅启用所需的配置。
4.2、sys系统库使用
在sys系统库下包含很多视图,它们以各种方式对performance_schema表进行聚合计算展示。这些视图大部分是成对出现的,两个视图名称相同,但有一个视图是带“x$”前缀的,例如:host_summary_by_file_io和x$host_summary_by_file_io,代表按照主机进行汇总统计的文件I/O性能数据, 两个视图访问的数据源是相同的,但是在创建视图的语句中,不带“x$”前缀的视图显示的是相关数值经过单位换算后的数据(单位是毫秒、秒、分钟、小时、 天等),带“x$”前缀的视图显示的是原始的数据(单位是皮秒)。
查看慢SQL慢在哪里
如果我们频繁地在慢查询日志中发现某个语句执行缓慢,且在表结构、索引 结构、统计信息中都无法找出原因时,则可以利用sys系统库中的杀手锏: sys.session视图结合performance_schema的等待事件来找出症结所在。那么session视图有什么用呢?使用它可以查看当前用户会话的进程列表信息,看看当前进程到底再干什么,注意,这个视图在MySQL5.7.9中才出现。
首先需要启用与等待事件相关功能:
call sys.ps_setup_enable_instrument(‘wait’);
call sys.ps_setup_enable_consumer(‘wait’);
然后模拟一下:
查询表的增、删、改、查数据量和I/O耗时统计
select * from schema_table_statistics_with_buffer\G
除此之外,通过sys还可以查询查看InnoDB缓冲池中的热点数据、查看是否有事务锁等待、查看未使用的,冗余索引、查看哪些语句使用了全表扫描等等。
5、mysql系统库
5.1、权限系统表
• user:包含用户账户、全局权限和其他非权限列表(安全配置字段和资源控制字段)。
• db:数据库级别的权限表。该表中记录的权限信息代表用户是否可以使用这些权限来访问被授予访问的数据库下的所有对象(表或存储程序)。
• tables_priv:表级别的权限表。
• columns_priv:字段级别的权限表。
• procs_priv:存储过程和函数权限表。
• proxies_priv:代理用户权限表。
提示: 要更改权限表的内容,应该使用账号管理语句(如:CREATE USER、GRANT、 REVOKE等)来间接修改,不建议直接使用DML语句修改权限表。
5.2、统计信息表
当innodb_stats_persistent = ON时全局开启统计信息的持久化功能,默认是开启的
show variables like ‘innodb_stats_persistent’;
如果要单独关闭某个表的持久化统计功能,则可以通过ALTER TABLE tbl_name STATS PERSISTENT = 0语句来修改。
innodb_table_stats
innodb_table_stats 表提供查询与表数据相关的统计信息。
• database_name:数据库名称。
• table_name:表名、分区名或子分区名。
• last_update:表示InnoDB上次更新统计信息行的时间。
• n_rows:表中的估算数据记录行数。
• clustered_index_size:主键索引的大小,以页为单位的估算数值。
• sum_of_other_index_sizes:其他(非主键)索引的总大小,以页为单位的估算数值。
innodb_index_stats
innodb_index_stats表提供查询与索引相关的统计信息。
select * from innodb_index_stats where table_name = ‘account’;
• database_name:数据库名称。
• table_name:表名、分区表名、子分区表名。
• index_name:索引名称。
• last_update:表示InnoDB上次更新统计信息行的时间。
• stat_name:统计信息名称,其对应的统计信息值保存在stat_value字段中。
• stat_value:保存统计信息名称stat_name字段对应的统计信息值。
• sample_size:stat_value字段中提供的统计信息估计值的采样页数。
• stat_description:统计信息名称stat_name字段中指定的统计信息的说明。 从表的查询数据中可以看到:
• stat_name 字段一共有如下几个统计值。
■ size:当stat_name字段为size值时,stat_value字段值表示索引中的总页数量。
■ n_leaf_pages:当stat_name字段为n_leaf_pages值时,stat_value字段值表示索引叶子页的数量。
■ n_diff_pfxNN:NN代表数字(例如 01、02 等)。当stat_name字段为n_diff_pfxNN值时,stat_value 字段值表示索引的first column(即索引的最前索引列,从索引定义顺序的第一个列开始)列的唯一值数量。例如:当NN为 01时,stat_value字段值就表示索引的第一个列的唯一值数量;当NN为02 时, stat_value字段值就表示索引的第一个和第二个列组合的唯一值数量,依此类推。 此外,在stat_name = n_diff_pfxNN的情况下,stat_description 字段显示一个以逗号分隔的计算索引统计信息字段的列表。
• 从index_name字段值为PRIMARY数据行的stat_description字段的描述信息“id”中可以看出,主键索引的统计信息只包括创建主键索引时显式指定的列。• 从index_name字段值为u_idx_day_status数据行的stat_description字段的描述信息“insert_time,order_status,expire_time”中可以看出,唯一索引的统 计信息只包括创建唯一索引时显式指定的列。
• 从index_name字段值为idx_order_no数据行的stat_description字段的描述信息“order_no,id”中可以看出,普通索引(非唯一的辅助索引)的统计信息包括了显式定义的列和主键列。
5.3、日志记录表
MySQL的日志系统包含:普通查询日志、慢查询日志、错误日志(记录服务 器启动时、运行中、停止时的错误信息)、二进制日志(记录服务器运行过程中 数据变更的逻辑日志)、中继日志(记录从库 I/O 线程从主库获取的主库数据变 更日志)、DDL 日志(记录 DDL 语句执行时的元数据变更信息。在MySQL5.7 中只支持写入文件中,在MySQL8.0中支持写入innodb_ddl_log表中。在MySQL5.7中,只有普通查询日志、慢查询日志支持写入表中(也支持写入文件中),可以通过log_output=TABLE设置保存到mysql.general_log表和mysql.slow_log表中, 其他日志类型在MySQL5.7中只支持写入文件中。
general_log
general_log表提供查询普通SQL语句的执行记录信息,用于查看客户端到底 在服务器上执行了什么SQL语句。
缺省不开启
show variables like ‘general_log’;
开启
set global log_output=‘TABLE’; – 'TABLE,FILE’表示同时输出到表和文件
set global general_log=on;
show variables like ‘general_log’;
任意执行一个查询后
select * from mysql.general_log\G
slow_log
slow_log表提供查询执行时间超过long_query_time设置值的SQL语句、未使用索引的语句(需要开启参数log_queries_not_using_indexes=ON)或者管理语句(需要开启参数 log_slow_admin_statements=ON)。
5.4、复制信息表
复制信息表在从库复制主库的数据期间,用于保存从主库转发到从库的binlog(二进制日志)事件,记录有关relay log(中继日志)当前状态和位置的信息。
master.info文件或者mysql.slave_master_info表:用于保存从库的I/O线程连接主库的连接状态、账号、IP地址、端口、密码,以及I/O线程当前读取主库 binlog的文件和位置信息(称为I/O线程信息日志)。在默认情况下,I/O线程的 连接信息和状态保存在master.info文件中(默认位置在datadir下,可以使用master_info_file参数指定master.info文件路径。注:在MySQL5.7.x较新的版本以及8.0.x版本中该参数已经被移除)。如果需要保存在mysql.slave_master_info表中,则需要在服务器启动之前设置master_info_repository=TABLE。
relay_log.info文件或者mysql.slave_relay_log_info表:当从库的I/O线程从主库获取到最新的binlog事件信息后会先写入从库本地的relay log中,然后SQL 线程再去读取relay log解析并重放。relay_log.info文件或者mysql.slave_relay_log_info表就是用于记录最新的relay log的文件和位置,以及SQL线程当前重放的事件对应的主库binlog的文件和位置信息的(SQL线程位置被称为SQL线程信息日志)。在默认情况下,relay log的位置信息和SQL线程的位置信息保存在relay-log.info文件中(默认位置在datadir下,可以使用relay_log_info_file选项指定relay-log.info文件路径)。如果需要保存在mysql.slave_relay_log_info表中,则需要在服务器启动之前设置relay_log_info_repository=TABLE。
1、概念
锁是计算机协调多个进程或线程并发访问某一资源的机制
在数据库中,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、 有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个 重要因素
锁对数据库而言显得尤其重要,也更加复杂
2、MySQL中的锁
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁(gap 锁,间隙锁):开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度 界于表锁和行锁之间,并发度一般
3、表锁与行锁的使用场景
表级锁更适合于以查询为主,只有少量按索引条件更新数据的应用,如 OLAP系统
行级锁则更适合于有大量按索引条件并发更新少量不同数据,同时又有并发查询的应用,如 一些在线事务处理(OLTP)系统
4、MyISAM锁
MySQL的表级锁有两种模式:
表共享读锁(Table Read Lock)
表独占写锁(Table Write Lock)
5、MyISAM锁总结
读锁,对MyISAM表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求
读锁,对MyISAM表的读操作,不会阻塞当前session对表读,当对表进行修改会报错
读锁,一个session使用LOCK TABLE命令给表f加了读锁,这个session可以查询锁定表中的记录,但更新或访问其他表都会提示错误;
写锁,对MyISAM表的写操作,则会阻塞其他用户对同一表的读和写操作;
写锁,对MyISAM表的写操作,当前session可以对本表做CRUD,但对其他表进行操作会报错
6、InnoDB锁
共享锁又称:读锁。当一个事务对某几行上读锁时,允许其他事务对这几行进行读操作,但不允许其进行写操作,也不允许其他事务给这几行上排它锁,但允许上读锁。
排它锁又称:写锁。当一个事务对某几个上写锁时,不允许其他事务写,但允许读。更不允许其他事务给这几行上任何锁。包括写锁。
7、语法
上共享锁的写法:lock in share mode
例如: select * from 表 where 条件 lock in share mode;
上排它锁的写法:for update
例如:select * from 表 where 条件 for update;
8、注意
两个事务不能锁同一个索引
insert ,delete , update 在事务中都会自动默认加上排它锁
行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了
1. 什么存储引擎支持事务
1.1、查看数据库下面是否支持事务(InnoDB 支持)
show engines;
1.2、查看 mysql 当前默认的存储引擎
show variables like ‘%storage_engine%’;
1.3、查看某张表的存储引擎
show create table 表名 ;
1.4、对于表的存储结构的修改
建立InnoDB表:Create table … type=InnoDB; Alter table table_name type=InnoDB;
2.事务特性
事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性
2.1、原子性(atomicity)
一个事务必须被视为一个不可分割的最小单元,整个事务中的所有操作要么全部提交成功, 要么全部失败,对于一个事务来说,不可能只执行其中的一部分操作
2.2、一致性(consistency)
一致性是指事务将数据库从一种一致性转换到另外一种一致性状态,在事务开始之前和事务结束之后数据库中数据的完整性没有被破坏
2.3、持久性(durability)
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,已经提交的修改数据也不会丢失
2.4、隔离性(isolation)
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。(对数据库的并行执行,应该像串行执行一样)
未提交读(READ UNCOMMITED) – 脏读
已提交读(READ COMMITED) --不可重复读
可重复读(REPEATABLE READ)
可串行化(SERIALIZABLE)
mysql 默认的事务隔离级别为 repeatable-read
show variables like ‘%tx_isolation%’;
2.4.1、事务并发问题
脏读:事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
不可重复读:事务A多次读取同一数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同一数据时,结果不一致。
幻读:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样,这就叫幻读。
不可重复读的和幻读很容易混淆,不可重复读侧重于修改,幻读侧重于新增或删除。解决不可重复读的问题只需锁住满足条件的行,解决幻读需要锁表
2.4.2、未提交读(READ UNCOMMITED) 脏读
show variables like ‘%tx_isolation%’;
set SESSION TRANSACTION ISOLATION LEVEL read UNCOMMITTED;
一个 session 中
start TRANSACTION
update account set balance = balance -50 where id = 1
另外一个session中查询
select * from account
回到第一个session中回滚事务
ROLLBACK
在第二个session中
select * from account
在另外一个session中读取到了为提交的数据,这部分的数据为脏数据
2.4.3、已提交读(READ COMMITED) 不可重复读
show variables like ‘%tx_isolation%’;
set SESSION TRANSACTION ISOLATION LEVEL read committed;
一个session中
start TRANSACTION
update account set balance = balance -50 where id = 1
另外一个session中查询 (数据并没改变)
select * from account
回到第一个session中回滚事务
commit
在第二个session中
select * from account (数据已经改变)
2.4.4、可重复读(REPEATABLE READ)
show variables like ‘%tx_isolation%’;
set SESSION TRANSACTION ISOLATION LEVEL repeatable read;
一个session中
start TRANSACTION
update account set balance = balance -50 where id = 1
另外一个session中查询 (数据并没改变)
select * from account
回到第一个session中回滚事务
commit
在第二个session中
select * from account (数据并未改变)
2.4.5、可串行化(SERIALIZABLE)
show variables like ‘%tx_isolation%’;
set SESSION TRANSACTION ISOLATION LEVEL serializable;
1.开启一个事务
begin
select * from account 发现3条记录
2.开启另外一个事务
begin
select * from account 发现也是3条记录
insert into account VALUES(4,‘deer’,500) 发现根本就不让插入
3.回到第一个事务 commit
2.4.6、间隙锁(gap 锁)
在mysql中,可重复读已经解决了幻读问题,借助的就是间隙锁
实验 1:
select @@tx_isolation;
create table t_lock_1 (a int primary key);
insert into t_lock_1 values(10),(11),(13),(20),(40);
begin
select * from t_lock_1 where a <= 13 for update;
在另外一个会话中
insert into t_lock_1 values(21) 成功
insert into t_lock_1 values(19) 阻塞
在rr隔离级别中会扫描到当前值(13)的下一个值(20),并把这些数据全部加锁
实验2:
create table t_lock_2 (a int primary key,b int, key (b));
insert into t_lock_2 values(1,1),(3,1),(5,3),(8,6),(10,8);
会话1
BEGIN
select * from t_lock_2 where b=3 for update;
1 3 5 8 10
1 1 3 6 8
会话2
select * from t_lock_2 where a = 5 lock in share mode; – 不可执行,因为 a=5 上有一把记录锁
insert into t_lock_2 values(4, 2); – 不可以执行,因为 b=2 在(1, 3]内
insert into t_lock_2 values(6, 5); – 不可以执行,因为 b=5 在(3, 6)内
insert into t_lock_2 values(2, 0); – 可以执行,(2, 0)均不在锁住的范围内 insert into t_lock_2 values(6, 7); – 可以执行,(6, 7)均不在锁住的范围内 insert into t_lock_2 values(9, 6); – 可以执行
insert into t_lock_2 values(7, 6); – 不可以执行
二级索引锁住的范围是 (1, 3],(3, 6)
主键索引只锁住了 a=5 的这条记录 [5]
1、慢查询基本配置
slow_query_log 启动停止慢查询日志
slow_query_log_file 指定慢查询日志得存储路径及文件(默认和数据文件放一起)
long_query_time 指定记录慢查询日志 SQL 执行时间得伐值(单位:秒,默认 10 秒)
log_queries_not_using_indexes 是否记录未使用索引的SQL
log_output 日志存放的地方【TABLE】【FILE】【FILE,TABLE】
配置了慢查询后,它会记录符合条件的SQL
包括: 查询语句、数据修改语句、已经回滚的SQL
通过下面命令查看上面的配置
show VARIABLES like ‘%slow_query_log%’;
show VARIABLES like ‘%slow_query_log_file%’;
show VARIABLES like ‘%long_query_time%’;
show VARIABLES like ‘%log_queries_not_using_indexes%’;
show VARIABLES like ‘log_output’;
set global long_query_time=0; – 默认10秒,这里为了演示方便设置为0
set GLOBAL slow_query_log = 1; – 开启慢查询日志
set global log_output=‘FILE,TABLE’; – 项目开发中日志只能记录在日志文件中,不能记表中
设置完成后,查询一些列表可以发现慢查询的日志文件里面有数据了。
2、慢查询解读
从慢查询日志里面摘选一条慢查询日志,数据组成如下
为解读方便,慢查询格式显示
第一行:用户名 、用户的 IP 信息、线程 ID 号
第二行:执行花费的时间【单位:毫秒】
第三行:执行获得锁的时间
第四行:获得的结果行数
第五行:扫描的数据行数
第六行:这 SQL 执行的具体时间
第七行:具体的SQL语句
3、慢查询分析
3.1、mysqldumpslow
语法:
mysqldumpslow -s r -t 10 localhost-slow.log
-s order (c,t,l,r,at,al,ar)
c:总次数
t:总时间
l:锁的时间
r:总数据行
at,al,ar :t,l,r 平均数 【例如:at = 总时间/总次数】
-t top 指定取前面几条作为结果输出
mysqldumpslow -s r -t 10 localhost-slow.log
3.2、pt_query_digest
待扩展
1. MySql中的索引
MySql中的索引其实也是这么一回事,我们可以在数据库中建立一系列的索引,比如创建主键的时候默认会创建主键索引,上图是一种 BTREE 的索引。每一个节点都是主键的ID当我们通过ID来查询内容的时候,首先去查索引库,在到索引库后能快速的定位索引的具体位置。
2. 二叉树(Binary Tree)
每个节点至多只有二棵子树
二叉树的子树有左右之分,次序不能颠倒;
一棵深度为 k,且有2^k-1个节点,称为满二叉树(Full Tree);
一棵深度为 k,且 root 到k-1层的节点树都达到最大,第k层的所有节点都连续集中在最左边,此时为完全二叉树(Complete Tree)
3. 平衡二叉树(AVL-树)
左子树和右子树都是平衡二叉树;
左子树和右子树的高度差绝对值不超过 1;
平衡二叉树
非平衡二叉树
平衡二叉树的遍历
前序 :6 ,3, 2, 5,7, 8(ROOT 节点在开头, 中 -左-右 顺序)
中序 :2, 3, 5, 6,7, 8(中序遍历即为升序,左- 中 -右 顺序)
后序 :2, 5, 3, 8,7, 6 (ROOT 节点在结尾,左-右- 中 顺序)
4. B+树
4.1、B+树的定义
数据只存储在叶子节点上,非叶子节点只保存索引信息;
非叶子节点(索引节点)存储的只是一个 Flag,不保存实际数据记录;
索引节点指示该节点的左子树比这个 Flag 小,而右子树大于等于这个 Flag;
叶子节点本身按照数据的升序排序进行链接(串联起来);
叶子节点中的数据在物理存储上是无序的,仅仅是在逻辑上有序(通过指针串在一 起);
4.2、B+树的作用
在块设备上,通过B+树可以有效的存储数据;
所有记录都存储在叶子节点上,非叶子(non-leaf)存储索引(keys)信息;
B+树含有非常高的扇出(fanout),通常超过100,在查找一个记录时,可以有效的减少IO操作;
4.3、B+树的扇出(fan out)
该B+树高度为2
每叶子页(LeafPage)4条记录
扇出数为5
叶子节点(LeafPage)由小到大(有序)串联在一起
扇出: 是每个索引节点(Non-LeafPage)指向每个叶子节点(LeafPage)的指针
扇出数 = 索引节点(Non-LeafPage)可存储的最大关键字个数 + 1
图例中的索引节点(Non-LeafPage)最大可以存放4个关键字,但实际使用了3 个;
4.4、B+树的插入操作
B+树的插入必须保证插入后叶子节点中的记录依然排序。
5. 索引的分类
普通索引:即一个索引只包含单个列,一个表可以有多个单列索引
唯一索引:索引列的值必须唯一,但允许有空值
复合索引:即一个索引包含多个列
聚簇索引(聚集索引):并不是一种单独的索引类型,而是一种数据存储方式。具体细节取决于不同的实现,InnoDB的聚簇索引其实就是在同一个结构中保存了B-Tree索引(技术上来说是 B+Tree)和数据行。
非聚簇索引:不是聚簇索引,就是非聚簇索引
自适应哈希索引: B+树的查找次数,取决于B+树的高度,在生产环境中,B+树的高度一般为3~4层,故需要3~4次的IO查询。所以在InnoDB存储引擎内部自己去监控索引表,如果监控到某个索引经常用,那么就认为是热数据,然后内部自己创建一个hash索引,称之为自适应哈希索引( Adaptive Hash Index,AHI),创建以后,如果下次又查询到这个索引, 那么直接通过hash算法推导出记录的地址,直接一次就能查到数据,比重复去B+tree索引中查询三四次节点的效率高了不少。
6. 基础语法
查看索引
SHOW INDEX FROM table_name
创建索引
CREATE [UNIQUE ] INDEX indexName ON mytable(columnname(length)); ALTER TABLE 表名 ADD [UNIQUE ] INDEX [indexName] ON (columnname(length))
删除索引
DROP INDEX [indexName] ON mytable;
7. 执行计划
7.1、执行计划定义
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL 是如何处理你的SQL语句的。分析你的查询语句或是表结构的性能瓶颈
7.2、执行计划作用
表的读取顺序
数据读取操作的操作类型
哪些索引可以使用
哪些索引被实际使用
表之间的引用
每张表有多少行被优化器查询
7.3、执行计划语法
在SQL查询的前面加上EXPLAIN关键字就行
比如:EXPLAIN select * from table1
7.4、执行计划详解
7.4.1、ID列
ID列:描述select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序根据ID的数值结果可以分成一下三种情况
id相同:执行顺序由上至下
id不同:如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行
id相同不同:同时存在
7.4.2、select_type列
select_type: 查询的类型, 主要是用于区别:普通查询、联合查询、子查询等的复杂查询
类型如下
7.4.3、table列
显示这一行的数据是关于哪张表的
7.4.4、type列
type 显示的是访问类型,是较为重要的一个指标,结果值从最好到最坏依次是:
system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL
需要记忆的
system>const>eq_ref>ref>range>index>ALL
一般来说,得保证查询至少达到range级别,最好能达到ref。
7.4.5、possible_keys与key
possible_keys:可能使用的key
Key:实际使用的索引。如果为 NULL,则没有使用索引
查询中若使用了覆盖索引,则该索引和查询的select字段重叠
7.4.6、key_len
Key_len表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度。在不损失精确性的情况下,长度越短越好
key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的
key_len 表示索引使用的字节数,根据这个值,就可以判断索引使用情况,特别是在组合索引的时候,判断所有的索引字段是否都被查询用到。
char和varchar跟字符编码也有密切的联系,
latin1占用1个字节,gbk占用2个字节,utf8占用3个字节。(不同字符编码占用的存储空间不同)
7.4.6.1、字符类型
以上这个表列出了所有字符类型,但真正建所有的类型常用情况只是 CHAR、VARCHAR
A、字符类型-索引字段为 char 类型+不可为 Null 时
name 这一列为char(10),字符集为utf-8占用3个字节 keylen=103
B、字符类型-索引字段为 char 类型+允许为 Null 时
name 这一列为char(10),字符集为utf-8占用3个字节,外加需要存入一个null值 keylen=103+1(null) 结果为31
C、索引字段为varchar类型+不可为Null时
keylen=varchar(n)变长字段+不允许 Null=n*(utf8=3,gbk=2,latin1=1)+2
D、索引字段为varchar类型+允许为Null时
keylen=varchar(n)变长字段+允许 Null=n*(utf8=3,gbk=2,latin1=1)+1(NULL)+2
7.4.6.2、数值类型
7.4.6.3、日期和时间
7.4.6.4、总结
A、字符类型
变长字段需要额外的2个字节(VARCHAR值保存时只保存需要的字符数,另加一个字节来 记录长度(如果列声明的长度超过 255,则使用两个字节),所以 VARCAHR 索引长度计算时候 要加 2),固定长度字段不需要额外的字节。
而NULL都需要1个字节的额外空间,所以索引字段最好不要为NULL,因为 NULL让统计更加复杂并且需要额外的存储空间。
复合索引有最左前缀的特性,如果复合索引能全部使用上,则是复合索引字段的索引长度之和,这也可以用来判定复合索引是否部分使用,还是全部使用。
B、整数/浮点数/时间类型的索引长度
NOT NULL=字段本身的字段长度
NULL=字段本身的字段长度+1(因为需要有是否为空的标记,这个标记需要占用 1 个字节)
datetime类型在5.6中字段长度是5个字节,datetime类型在5.5中字段长度是8个字节
7.4.7、ref
显示索引的哪一列被使用了,如果可能的话,是一个常数。哪些列或常量被用于查找索引列上的值
7.4.8、rows
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数
7.4.9、extra
包含不适合在其他列中显示但十分重要的额外信息
A、覆盖索引
覆盖索引(Covering Index),一说为索引覆盖。
理解方式一:就是select的数据列只用从索引中就能够取得,不必读取数据行,MySQL可以利用索引返回select列表中的字段,而不必根据索引再次读取数据文件,换句话说查询列要被所建的索引覆盖。
理解方式二:索引是高效找到行的一个方法,但是一般数据库也能使用索引找到一个列的数据,因此它不必读取整个行。毕竟索引叶子节点存储了它们索引的数据;当能通过读取索引就可以得到想要的数据,那就不需要读取行了。一个索引包含了(或覆盖了)满足查询结果的数据就叫做覆盖索引
1、sql优化打油诗
全值匹配我最爱,最左前缀要遵守
带头大哥不能死,中间兄弟不能断
索引列上少计算,范围之后全失效
LIKE 百分写最右,覆盖索引不写*
不等空值还有OR,索引影响要注意
VAR引号不可丢, SQL优化有诀窍
2、批量导入
A、insert语句优化
提交前关闭自动提交
尽量使用批量insert语句
可以使用MyISAM存储引擎
B、LOAD DATA INFLIE
使用 LOAD DATA INFLIE ,比一般的insert语句快 20 倍
select * into OUTFILE ‘D:\product.txt’ from product_info
load data INFILE ‘D:\product.txt’ into table product_info
show VARIABLES like ‘secure_file_priv’
secure_file_priv 为NULL时,表示限制mysqld不允许导入或导出。
secure_file_priv 为/tmp时,表示限制mysqld只能在/tmp目录中执行导入导出,其他目录不能执行。
secure_file_priv 没有值时,表示不限制mysqld在任意目录的导入导出。 secure_file_priv=’’