论Mysql5.7.13架构组成之物理文件


防伪码:岁寒,然后知松柏之后凋也


一、MySQL Server 简介

什么是 MySQL

MySQL 是由 MySQL AB 公司(目前已经被ORACLE 公司收归麾下)自主研发的,目前 IT

最流行的开放源代码的数据库管理系统之一,它同时也是一个支持多线程高并发多用户的关

系型数据库管理系统。

MySQL 数据库以其简单高效可靠的特点,在最近短短几年的时间就从一个名不见经传的

数据库系统,变成一个在 IT 行业几乎是无人不知的开源数据库管理系统。从

小型的 web 网站,至大型的企业级应用,到处都可见其身影的存在。

MySQL 数据库在发展过程中一直有自己的三个原则:简单、高效、可靠。

MySQL 的主要适用场景

MySQL 是目前最为流行的开源数据库管理系统软件了。那么 MySQL 主要用于什么场景下

1Web 网站系统

Web 站点,是 MySQL 最大的客户群,MySQL 之所以能成为 Web 站点开发者们最青睐的数

据库管理系统,是因为 MySQL 数据库的安装配置都非常简单,使用过程中的维护也不像很

多大型商业数据库管理系统那么复杂,而且性能出色。还有一个非常重要的原因就是 MySQL

是开放源代码的,完全可以免费使用。

2)日志记录系统

MySQL 数据库的插入和查询性能都非常的高效,如果设计地较好,在使用 MyISAM 存储引

擎的时候,两者可以做到互不锁定,达到很高的并发性能。所以,对需要大量的插入和查询

日志记录的系统来说,MySQL 是非常不错的选择。比如处理用户的登录日志,操作日志等

是非常适合的应用场景。

3)数据仓库系统

随着现在数据仓库数据量的飞速增长,我们需要的存储空间越来越大。数据量的不断增长,

使数据的统计分析变得越来越低效,也越来越困难。怎么办?这里有几个主要的解决思路,

一个是采用昂贵的高性能主机以提高计算性能,用高端存储设备提高 I/O 性能,效果理想,

但是成本非常高;第二个就是通过将数据复制到多台使用大容量硬盘的廉价 pc server 上,

以提高整体计算性能和 I/O 能力,效果尚可,存储空间有一定限制,成本低廉;第三个,通

过将数据水平拆分,使用多台廉价的 pc server 和本地磁盘来存放数据,每台机器上面都只

有所有数据的一部分,解决了数据量的问题,所有 pc server 一起并行计算,也解决了计算

能力问题,通过中间代理程序调配各台机器的运算任务,既可以解决计算性能问题又可以解

I/O 性能问题,成本也很低廉。在上面的三个方案中,第二和第三个的实现,MySQL

有较大的优势。通过 MySQL 的简单复制功能,可以很好的将数据从一台主机复制到另外一

台,

不仅仅在局域网内可以复制,在广域网同样可以。当然,其他的数据库同样也可以做到,不

是只有 MySQL 有这样的功能。但是 MySQL 是免费的,其他数据库大多都是按照主机数量或

cpu 数量来收费,当我们使用大量的 pcserver 的时候,license 费用相当惊人。第一个方

案,基本上所有数据库系统都能够实现,但是其高昂的成本并不是每一个公司都能够承担的。

二、MySQL 架构组成

Mysql 物理文件组成:

1 日志文件  

主要包含:错误日志、查询日志、慢查询日志、事务日志、二进制日志。

日志是 mysql 数据库的重要组成部分。日志文件中记录着 mysql 数据库运行期间发生的变

化;也就是说用来记录 mysql 数据库的客户端连接状况、SQL 语句的执行情况和错误信息

等。当数据库遭到意外的损坏时,可以通过日志查看文件出错的原因,并且可以通过日志文

件进行数据恢复。

1、错误日志:Error Log

mysql 数据库中,错误日志功能是默认开启的。默认情况下,错误日志存储在 mysql

数据库的数据目录中。错误日志文件通常的名称为 hostname.err。其中,hostname

示服务器主机名。

默认情况下错误日志大概记录以下几个方面的信息:服务器启动和关闭过程中的信息、服务

器运行过程中的错误信息、事件调度器运行一个事件时产生的信息、在从服务器上启动服务

器进程时产生的信息。

1MySQL有很多系统变量可以设置,系统变量设置不同,会导致系统运行状态的不同。

因此 mysql 提供两组命令,分别查看系统设置和运行状态。

1、查看系统设置:

SHOW [GLOBAL | SESSION] VARIABLES[like_or_where]

SHOW VARIABLESshow thevalues of MySQL system variables.

2、运行状态:

SHOW [GLOBAL | SESSION] STATUS[like_or_where]

SHOW STATUSprovides serverstatus information.

方法 1(永久生效):配置文件设置 my.cnf

如:binlog_cache_size = 1M

方法 2(临时生效):set global binlog_cache_size = 1048576;

                            wKioL1h78FCDhO-qAABYSTjT658897.png-wh_50

2:查看 mysql 的版本

wKiom1h78F_jg5UvAABtcT2koss458.png-wh_50

wKioL1h78HOhTi2KAAGUr0I8UOQ146.png-wh_50

wKioL1h78ITRnXQ4AABQyAavLZk118.png-wh_50

一般而言,日志级别的定义没有会话变量都只是在全局级别下进行定义

错误日志的状态:

wKiom1h78JbB9gI8AAC9nN2boto490.png-wh_50

其中

log_error 定义为错误日志文件路径

更改错误日志位置可以使用 log-error 来设置形式如下

#vi /etc/my.cnf

wKiom1h78KjQvCKbAADuz9QGeW0080.png-wh_50

查看 mysql 错误日志:

#tail /usr/local/mysql/data/mysqld.err

wKioL1h78LvzZaRcAAHpBFKvCs8221.png-wh_50

为了方便维护需要,有时候会希望将错误日志中的内容做备份并重新开始记录,这时候

就可以利用 MySQL FLUSH LOGS 命令来告诉 MySQL 备份旧日志文件并生成新的日志文件。备份文件名以“.old”结尾。

删除错误日志:

数据库管理员可以删除很长时间之前的错误日志,以保证 mysql 服务器上的硬盘空间。

mysql 数据库中,可以使用 mysqladmin 命令开启新的错误日志。mysqladmin命令的

语法如下:

mysqladmin u root p flush-logs也可以登录 mysql 数据库中使用 FLUSH LOGS

语句来开启新的错误日志先重命名原来的错误日志文件,执行 mysqladmin u root p flush-logs 也可以登录

mysql 数据库中使用 FLUSH LOGS 语句来开启新的错误日志。

方式如下:

wKiom1h78M2hRI4CAAE3T0g4S8Y206.png-wh_50

更多信息请查阅官方文

档:http://dev.mysql.com/doc/refman/5.5/en/error-log.html

http://dev.mysql.com/doc/refman/5.6/en/error-log.html

http://dev.mysql.com/doc/refman/5.7/en/error-log.html

2、二进制日志:Binary Log& Binary Log Index

二进制日志,也就是我们常说的 binlog,也是 MySQL Server 中最为重要的日志之一,主要

用于记录修改数据或有可能引起数据改变的 mysql 语句,并且记录了语句发生时间、执行

时长、操作的数据等等。所以说通过二进制日志可以查询 mysql 数据库中进行了哪些变化。

一般大小体积上限为 1G

当我们通过“log-bin=file_name”打开了记录的功能之后,MySQL 会将所有修改数据库数据

query 以二进制形式记录到日志文件中,还包括每一条 query 所执行的时间,所消耗的

资源,以及相关的事务信息。

binlog 记录功能需要“log-bin=file_name”参数的显式指定才能开启,如果未指定 file_name

则会在数据目录下记录为 mysql-bin.*******代表 09 之间的某一个数字,来表示该日志

的序号)。

wKioL1h78OHiG279AAEGyCqc8zA453.png-wh_50

wKioL1h78PKinfmxAADbjQGWAoE396.png-wh_50

二进制开启状态:

wKiom1h78QXwZfg2AADXbvt_Xt8442.png-wh_50

binlog 还有其他一些附加选项参数:

  “max_binlog_size”设置 binlog 的最大存储上限,一般设置为 512M 1G,一般不能超过 1G

当日志达到该上限时,MySQL 会重新创建一个日志开始继续记录。不过偶尔也有超出该设

置的 binlog 产生,一般都是因为在即将达到上限时,产生了一个较大的事务,为了保证事务

安全,MySQL 不会将同一个事务分开记录到两个 binlog 中。

  “binlog-do-db=db_name”参数明确告诉 MySQL,需要对某个(db_name)数据库记录 binlog,如果有了“binlog-do-db=db_name”参数的显式指定,MySQL 会忽略针对其他数据库执行的

query,而仅仅记录针对指定数据库执行的query

  “binlog-ignore-db=db_name”与“binlog-do-db=db_name”完全相反,它显式指定忽略某个

db_name)数据库的 binlog 记录,当指定了这个参数之后,MySQL 会记录指定数据库以

外所有的数据库的 binlog

  “binlog-ignore-db=db_name”与“binlog-do-db=db_name”两个参数有一个共同的概念需要

大家理解清楚,参数中的 db_name 不是指 query 语句更新的数据所在的数据库,而是执行

query 的时候当前所处的数据库。不论更新哪个数据库的数据,MySQL 仅仅比较当前连接

所处的数据库(通过 use db_name 切换后所在的数据库)与参数设置的数据库名,而不会分

query 语句所更新数据所在的数据库。

  mysql-bin.index 文件(binary logindex)的功能是记录所有 Binary Log 的绝对路径,保证 MySQL

各种线程能够顺利的根据它找到所有需要的 Binary Log 文件。

  binlog_cache_size =32768 #默认值 32768binlog_cache_size:一个事务,在没有提

交(uncommitted)的时候,产生的日志,记录到 Cache 中;等到事务提交(committed)需

要提交的时候,则把日志持久化到磁盘。一般来说,如果我们的数据库中没有什么大事务,

写入也不是特别频繁,2MB4MB 是一个合适的选择。但是如果我们的数据库大事务较多,

写入量比较大,可以适当调高 binlog_cache_size。同时,我们可以通过 binlog_cache_use

以及 binlog_cache_disk_use 来分析设置的binlog_cache_size 是否足够,是否有大量的

binlog_cache 由于内存大小不够而使用临时文件(binlog_cache_disk_use)来缓存了。

wKiom1h78RbSJPMwAACnoLabt1w305.png-wh_50

binlog_stmt_cache_size= 32768 #当非事务语句使用二进制日志缓存,但是超

binlog_stmt_cache_size 时,使用一个临时文件来存放这些语句。

概念解释:

事务表支持将批处理当做一个完整的任务统一提交或回滚,即对包含在事务中的多条语句要

么全执行,要么全部不执行

非事务表则不支持此种操作,批处理中的语句如果遇到错误,在错误前的语句执行成功,之

后的则不执行。

log-bin = mysql-bin#指定 binlog 的位置,默认在数据目录下。

binlog-format= {ROW|STATEMENT|MIXED}#指定二进制日志的类型,默认为 MIXED

概念解释:mysql复制主要有三种方式:基于SQL语句的复制(statement-based replication, SBR)

基于行的复制(row-based replication, RBR),混合模式复制(mixed-basedreplication, MBR)。对

应的,binlog 的格式也有三种:STATEMENTROWMIXED

STATEMENT  模式(SBR

每一条会修改数据的 sql 语句会记录到 binlog 中。优点是并不需要记录每一行的数据变化,

减少了 binlog 日志量,节约 IO,提高性能。缺点是在某些情况下会导致 master-slave 中的数

据不一致( sleep()函数,last_insert_id(),以及 user-definedfunctions(udf)等会出现问题)

ROW  模式(RBR

不记录每条 sql 语句的信息,仅需记录哪条数据被修改了,修改成什么样了。缺点是会产生

大量的日志,让日志暴涨。

MIXED  模式(MBR

以上两种模式的混合使用,一般的复制使用 STATEMENT 模式保存 binlog,对于 STATEMENT

模式无法复制的操作使用 ROW 模式保存 binlogMySQL 会根据执行的 SQL 语句选择日志保

存方式。即交替使用行和语句、由 mysql 服务器自行判断。

其中基于行的定义格式数据量会大一些但是可以保证数据的精确性

sync_binlog= 10#设定多久同步一次二进制日志至磁盘文件中,0 表示不同步,

任何正数值都表示对二进制每多少次写操作之后同步一次。当 autocommit 的值

1 时,每条语句的执行都会引起二进制日志同步,否则,每个事务的提交会引

起二进制日志同步

通过编辑 my.cnf 中的 log-bin 选项可以开启二进制日志;形式如下:

log-bin[=DIR/[filename]]

其中,DIR 参数指定二进制文件的存储路径;filename 参数指定二级制文件的文件名,其

形式为 filename.numbernumber 的形式为 000001000002 等。每次重启 mysql

服务或运行 mysql> flush logs;都会生成一个新的二进制日志文件,这些日志文件的

number会不断地递增。除了生成上述的文件外还会生成一个名为 filename.index 的文件。

这个文件中存储所有二进制日志文件的清单又称为二进制文件的索引

wKioL1h78Sfynuk5AAEKLEPJLrs238.png-wh_50

查看二进制日志:

二进制日志的定义方式为二进制格式;使用此格式可以存储更多的信息,并且可以使写入二

进制日志的效率更高。但是不能直接使用查看命令打开并查看二进制日志。wKioL1h78TnBO4TxAAB50QskOmE290.png-wh_50

当前使用的二进制文件及所处位置

wKiom1h78VGTiBCZAACXk94zJ5Q076.png-wh_50

wKioL1h78W6CWm4wAADDF6tz1G4748.png-wh_50

查看当前二进制文件的信息:

wKiom1h78X-Rqf2aAAElulO-HaQ620.png-wh_50

查看二进制日志信息的命令:

语法格式: SHOW BINLOG EVENTS[IN 'log_name'][FROM pos] [LIMIT [offset,] row_count]

#查看所有的二进制信息

mysql>show binlog events\G;

#查看指定日志的二进制信息

mysql>show binlog events in 'mysql-bin.000006'\G;

#从指定的事件位置开始

mysql>showbinlogevents in 'mysql-bin.000006' from1192;

wKiom1h78ZPitGo0AAFQH773TGo472.png-wh_50

注:二进制日志的记录位置:通常为上一个事件执行结束时间的位置

#指定偏移量(不是语句,是事件)

mysql>show binlog events in 'mysql-bin.000017' from 154 limit 3;

wKioL1h78azil3-jAADULPSrOUc846.png-wh_50

命令行下查看二进制日志:

由于无法使用 cat 等方式直接打开并查看二进制日志;所以必须使用 mysqlbinlog 命令。

但是当正在执行 mysql 读写操作时建议不要使用此打开正在使用的二进制日志文件;若非

要打开可 flush logsmysqlbinlog 命令的使用方式:

wKiom1h78cDgIDhPAAAvMrrmX0k332.png-wh_50

/*!50530SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;

/*!50003SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,COMPLETION_TYPE=0*/;

DELIMITER/*!*/;

#at 4   事务开始处

#170116  3:28:26 server id 1  end_log_pos 310 CRC32 0xc0a842ab     Query       thread_id=7         exec_time=0   error_code=0

#170116  3:28:26年月日的简写方式:end_log_pos事件结束处:thread_id=7哪个会话线程创建的此语句

exec_time=0 执行时长单位为秒;error_code=0 错误代码 0 表示没有

删除二进制日志信息:

二进制日志会记录大量的信息(其中包含一些无用的信息)。如果很长时间不清理二进制日

志,将会浪费很多的磁盘空间。但是,删除之后可能导致数据库崩溃时无法进行恢复,所以

若要删除二进制日志首先将其和数据库备份一份,其中也只能删除备份前的二进制日志,新

产生的日志信息不可删。也不可在关闭 mysql 服务器之后直接删除因为这样可能会给数据

库带来错误的。若非要删除二进制日志需要做如下操作:导出备份数据库和二进制日志文件

进行压缩归档存储。删除二进制文件的方法如下:

方法 1:根据文件或时间点来删除二进制日志:

语法形式:

mysql>PURGE { BINARY | MASTER } LOGS {TO 'log_name' | BEFORE datetime_expr }

TO 'log_name' 使

BEFOREdatetime_expr 指定把哪个时间之前的二进制文件删除了。

wKioL1h78fPyDblvAAEyiFhVr9c927.png-wh_50

方法 2 删除所有的二进制日志(慎用):

使用 RESET MASTER 语句可以删除所有的二进制日志。该语句的形式如下:

wKioL1h78gOC8AT5AAB6kF6faJg072.png-wh_50

不建议在生产环境下使用此操作;删除所有的二进制日志后,Mysql 将会重新创建新的二

进制日志。新二进制日志的编号从 000001 开始。

3、事务日志(或称 redo 日志)

事务日志(InnoDB 特有的日志)可以帮助提高事务的效率。使用事务日志,存储引擎在修

改表的数据时只需要修改其内存拷贝,再把修改行为记录到持久在硬盘上的事务日志中,而

不用每次都将修改的数据本身持久到磁盘。事务日志采用追加的方式,因此写日志的操作是

磁盘上一小块区域内的顺序 I/O,而不像随机 I/O 需要在磁盘的多个地方移动磁头,所以

采用事务日志的方式相对来说要快得多。事务日志持久以后,内存中被修改的数据在后台可

以慢慢的刷回到磁盘。目前大多数的存储引擎都是这样实现的。

如果数据的修改已经记录到事务日志并持久化,但数据本身还没有写回磁盘,此时系统崩溃,

存储引擎在重启时能够自动恢复这部分修改的数据。具有的恢复方式则视存储引擎而定。

一般情况下,mysql 会默认提供多种存储引擎,你可以通过下面的查看:

查看你的 mysql 现在已提供什么存储引擎:

mysql>show engines;

看你的 mysql 当前默认的存储引擎:

mysql>show variables like '%storage_engine%';

你要看某个表用了什么引擎(在显示结果里参数 engine 后面的就表示该表当前用的存储引

):

mysql>show create table 表名;

注:

createtable 库名.表名 engine = innodb;

这样就可以将表的引擎变更为 innodb 引擎了。

也可以在创建表之后通过下面语句来变更:

altertable 库名.表名 engine =innodb;

查看事务日志的定义:

mysql>show global variables like '%log%';

|innodb_flush_log_at_timeout| 1 |

|innodb_flush_log_at_trx_commit | 1   #在事务提交时 innodb 是否同步日志从缓冲区到文件中,

当这个值为 1(默认值)之时,在每个事务提交时,日志缓冲被写到日志文件,对日志文件做到磁盘操作

的刷新,性能会很差造成大量的磁盘I/O 但这种方式最安全;如果设为 2,每次提交事务都会写日志,但并

不会执行刷的操作。每秒定时会刷到日志文件。要注意的是,并不能保证 100%每秒一定都会刷到磁盘,这

要取决于进程的调度。每次事务提交的时候将数据写入事务日志,而这里的写入仅是调用了文件系统的写

入操作,而文件系统是有缓存的,所以这个写入并不能保证数据已经写入到物理磁盘。设置为 0,日志缓

冲每秒一次地被写到日志文件,并且对日志文件做到磁盘操作的刷新,但是在一个事务提交不做任何操作。

注:刷写的概念

刷写其实是两个操作,刷(flush)和写(write),区分这两个概念是很重要的。

在大多数的操作系统中,把 Innodb log buffer(内存)写入日志(调用系统调

write),只是简单的把数据移到操作系统缓存中,操作系统缓存同样指的是内

存。并没有实际的持久化数据。

所以,通常设为 0 2 的时候,在崩溃或断电的时候会丢失最后一秒的数据,因

为这个时候数据只是存在于操作系统缓存。之所以说“通常”,可能会有丢失不只

1 秒的数据的情况,比如说执行 flush 操作的时候阻塞了。

总结

设为 1 当然是最安全的,但性能页是最差的(相对其他两个参数而言,但不是不

能接受)。如果对数据一致性和完整性要求不高,完全可以设为 2,如果只最求性

能,例如高并发写的日志服务器,设为 0 来获得更高性能

|

|innodb_locks_unsafe_for_binlog| OFF |

|innodb_log_buffer_size| 16777216 |

|  innodb_log_checksums  |  ON

|

|innodb_log_compressed_pages| ON |

|innodb_log_file_size| 50331648 #日志文件大小 |

|innodb_log_files_in_group| 2 # DB中设置几组事务日志,默认是 2

|

|innodb_log_group_home_dir| ./#定义 innodb 事务日志组的位置,此位置设置默认为 MySQL

datadir

每个事务日志都是大小为 50 兆的文件(不同版本的 mysql 有差异):

mysql 中默认以 ib_logfile0,ib_logfile1 名称存在

wKiom1h78h6DaRvVAABrGR4rlNo598.png-wh_50

4、慢查询日志:slow query log

顾名思义,慢查询日志中记录的是执行时间较长的 query,也就是我们常说的 slowquery

慢查询日志采用的是简单的文本格式,可以通过各种文本编辑器查看其中的内容。其中

记录了语句执行的时刻,执行所消耗的时间,执行用户,连接主机等相关信息。

慢查询日志的作用:

慢查询日志是用来记录执行时间超过指定时间的查询语句。通过慢查询日志,可以查找出哪

些查询语句的执行效率很低,以便进行优化。一般建议开启,它对服务器性能的影响微乎其

微,但是可以记录 mysql 服务器上执行了很长时间的查询语句。可以帮助我们定位性能问

题的。MySQL 还提供了专门用来分析满查询日志的工具程序 mysqldumpslow,用来帮助数

据库管理人员解决可能存在的性能问题。

查看慢查询日志的定义:

wKiom1h78jCCMd7DAACtfSDiAOI828.png-wh_50

wKioL1h78kKDW5NFAADkVAcpuCU799.png-wh_50

启动和设置慢查询日志:

方法 1:通过配置文件 my.cnf 开启慢查询日志:

注:在不同的 mysql 版本中,开启慢查询日志参数不太一样,不过都可以通过 show variables

like"%slow%" show variables like "%long%"查看出来。

wKiom1h78lPi9sQ6AADGz5gtwko602.png-wh_50

其中:

slow_query_log off 关闭状态 on 开启状态

slow_query_log_file慢查询日志存放地点

long_query_time选项来设置一个时间值,时间以秒为单位,可以精确到微秒。如果查询

时间超过了这个时间值(默认为 10 秒),这个查询语句将被记录到慢查询日志中,设置为 0

的话表示记录所有的查询。

slow_launch_time表示如果建立线程花费了比这个值更长的时间,slow_launch_threads

数器将增加

注:如果不指定存储路径,慢查询日志默认存储到 mysql 数据库的数据文件下,如果不指

定文件名,默认文件名为 hostname-slow.log

修改 my.cnf 文件:

wKioL1h78maxlcBIAAFI1Q8hdzw464.png-wh_50

重启 mysqld 服务

再次查询慢查询日志定义:

wKiom1h78niwwiUmAAEaBs2hv8A915.png-wh_50

方法 2:通过登录 mysql 服务器直接定义,方式如下:

mysql>setglobalslow_query_log=1; #开启慢查询日志

QueryOK, 0 rowsaffected (0.35 sec)

mysql>setsessionlong_query_time=0.0001; #更改时间(当前 session 中,退

出则重置)

QueryOK, 0 rowsaffected (0.00 sec)

mysql>setgloballong_query_time=0.0001; #更改时间(全局中,重启服务则

重置)

mysql>SHOWVARIABLES LIKE 'long%'; #查询定义时间

查看慢查询日志

mysql>use mysql

mysql>selectuser,hostfrom user where user="root";

wKioL1h78pvTSSQjAAHKEiKr5lc348.png-wh_50

wKiom1h78uCgca4vAAN5yADUzok977.png-wh_50

或用系统查看文件内容命令如 cat 直接查看慢日志文件

第一行表示记录日志时的时间。其格式是 YYYY-MM-DD HH:MM:SS。我们可以看出上面的查

询记录于 2017 1 15 日下午 20:3100 - 注意:这个是服务器时间.

MySql用户、服务器以及主机名第三行表示总的查询时间、锁定时间、"发送"或者返回的行

Query_time:0.000542 表示用了 0.000542

Lock_time:0.000088 表示锁了 0.000088

Rows_sent:6 表示返回 6

Rows_examined:6 表示一共查了 6

SETtimestamp=UNIXTIME; 这是查询实际发生的时间

何将其变成一个有用的时间,将 Unix 时间转成一个可读的时间,可以使用 date d@日志

中的时间戳

wKiom1h78vKyYjVKAABO_EqgAE4092.png-wh_50

以看到查询进行的同时记录了该日志,但是对于一台超负载的服务器常常并非如此。因此记

住:SET timestamp= value 才是实际的查询的执行时间。

慢查询分析 mysqldumpslow

我们可以通过打开 log 文件查看得知哪些 SQL 执行效率低下。从日志中,可以发现查询时间

超过 long_query_time 时间 query 为慢查询,而小于 long_query_time 时间 的没有

出现在此日志中。

如果慢查询日志中记录内容很多,可以使用 mysqldumpslow 工具(MySQL 客户端安装自

带)来对慢查询日志进行分类汇总。mysqldumpslow 对日志文件进行了分类汇总,显示汇

总后摘要结果

进入 log 的存放目录,运行

wKioL1h78wbyLif5AAMC3QF2GFI432.png-wh_50

注:

mysqldumpslow-sc -t 10 /database/mysql/slow-query.log

这会输出记录次数最多的 10 SQL 语句,其中:

-s,是表示按照何种方式排序,ctlr 分别是按照记录数、查询时间、锁定时间、返回行

数来排序;

-t, top n 的意思,即为返回前面多少条的数据;

-g,后边可以写一个正则匹配模式,大小写不敏感的;

详细选项查看帮助:#mysqldumpslow --help

例如:

/path/mysqldumpslow-s r -t 10 /database/mysql/slow-log

得到返回记录集最多的 10 个查询。

/path/mysqldumpslow-s t -t 10 -g “left join” /database/mysql/slow-log

得到按照时间排序的前 10 条里面含有左连接的查询语句。

2 )数据文件

MySQL 中每一个数据库都会在定义好(或者默认)的数据目录下存在一个以数据库名字

命名的文件夹,用来存放该数据库中各种表数据文件。不同的 MySQL 存储引擎有各自不同

的数据文件。如 MyISAM 用“.MYD”作为扩展名,Innodb 用“.ibd”,Archive 用“.arc”,CSV

用“.csv,等等。

如何查看你的 mysql 现在已提供什么存储引擎:

mysql>show engines;

看你的 mysql 当前默认的存储引擎:

mysql>show variables like '%storage_engine%';

你要看某个表用了什么引擎(在显示结果里参数 engine 后面的就表示该表当前用的存储引

):

mysql>show create table 表名;

注:

createtable 库名.表名 engine = innodb;这样就可以将表的引擎变更为 innodb 引擎了。

登录 mysql,创建一个数据库如 testdb,并在数据库中创建一个表,如下图所示:

wKioL1h78x3hgtQqAACf62pFH24708.png-wh_50

查看数据库所在目录会发现数据目录下存在一个以数据库名字命名的文件夹

wKiom1h78y6BQ0iDAADgM61btnI986.png-wh_50

查看 testdb 目录的文件列表

wKiom1h78zzhpUHGAABGLXIOjKU890.png-wh_50

从上图可以看出表使用的是 innodb 存储引擎。

myisam 存储引擎创建一个测试表 tb2

wKioL1h7807zp1mNAABqLNg2_sk724.png-wh_50

查看数据库目录

wKiom1h782GiseYFAABW7rSZXJ4869.png-wh_50

注:修改 mysql 的默认存储引擎

1、查看 mysql 存储引擎命令,在 mysql>提示符下输入 show engines;字段 Support :Default

表示默认存储引擎

2 InnoDB my.cnf [mysqld]

default-storage-engine=INNODB一句

3、重启 mysql 服务器:mysqladmin -u root -pshutdown 或者 service mysqld restart 登录 mysql

数据库,

1、“.frm”文件

与表相关的元数据(meta)信息都存放在“.frm”文件中,包括表结构的定义信息等。不论

是什么存储引擎(MySQL 常用的两个存储引擎是 MyISAM InnoDB),每一个表都会有一

个以表名命名的“.frm”文件。所有的“.frm”文件都存放在所属数据库的文件夹下面。

MyISAM数据库表文件:.MYD 文件:表数据文件;.MYI 文件:索引文件

2、“.MYD”文件

.MYD”文件是 MyISAM 存储引擎专用,存放 MyISAM 表的数据。每一个 MyISAM 表都会有

一个“.MYD”文件与之对应,同样存放于所属数据库的文件夹下,和“.frm”文件在一起。

3、“.MYI”文件

.MYI”文件也是专属于 MyISAM 存储引擎的,主要存放 MyISAM 表的索引相关信息。对于

MyISAM存储来说,可以被 cache 的内容主要就是来源于“.MYI”文件中。每一个 MyISAM

表对应一个“.MYI”文件,存放于位置和“.frm”以及“.MYD”一样。

InnoDB采用表空间(tablespace)来管理数据,存储表数据和索引。

.ibd文件:单表表空间文件,每个表使用一个表空间文件(file per table),存放用户数据库

表数据和索引。

InnoDB共享表空间(即 InnoDB 文件集,ib-file set):ibdata1ibdata2 等,存储 InnoDB 系统

信息和用户数据库表数据和索引,所有表共用。

4、“.ibd”文件和 ibdata 文件

这两种文件都是存放 Innodb 数据的文件,之所以有两种文件来存放 Innodb 的数据(包括索

引),是因为 Innodb 的数据存储方式能够通过配置来决定是使用共享表空间存放存储数据,

还是独享表空间存放存储数据。独享表空间存储方式使用“.ibd”文件来存放数据,且每个

表一个“.ibd”文件,文件存放在和 MyISAM 数据相同的位置。如果选用共享存储表空间来

存放数据,则会使用 ibdata 文件来存放,所有表共同使用一个(或者多个,可自行配置)ibdata

文件。

ibdata文件可以通过innodb_data_home_dirinnodb_data_file_path两个参数共同配置组成,

innodb_data_home_dir配置数据存放的总目录,而 innodb_data_file_path 配置每一个文件的

名称。

innodb_data_file_path中可以一次配置多个 ibdata 文件。文件可以是指定大小,也可以是自

动扩展的,但是 Innodb 限制了仅仅只有最后一个 ibdata 文件能够配置成自动扩展类型。当

我们需要添加新的 ibdata 文件的时候,只能添加在 innodb_data_file_path 配置的最后,而且

必须重启 MySQL 才能完成 ibdata 的添加工作。不过如果我们使用独享表空间存储方式的话,

就不会有这样的问题。

总结:

共享表空间以及独占表空间都是针对数据的存储方式而言的。

共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中。

独占表空间: 每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm 表描

述文件,还有一个.ibd 文件。其中这个文件包括了单独一个表的数据内容以及索引内容。

两者之间的优缺点

共享表空间:

优点:

可以把表空间分成多个文件存放到各个磁盘上。数据和文件放在一起方便管理。

缺点:

所有的数据和索引存放到一个文件中,多个表及索引在表空间中混合存储,这样对于一个表

做了大量删除操作后表空间中将会有大量的空隙,特别是对于统计分析,日值系统这类应用

最不适合用共享表空间。

独立表空间:

优点:

1.每个表都有自已独立的表空间。

2.每个表的数据和索引都会存在自已的表空间中。

3.可以实现单表在不同的数据库中移动。

4.空间可以回收

相比较之下,使用独占表空间的效率以及性能会更高一点

查看当前数据库的表空间管理类型

wKioL1h783yADE-LAACA49RiUp8694.png-wh_50

ON代表独立表空间管理,OFF 代表共享表空间管理;(查看单表的表空间管理方式,需要查看每个表是否

有单独的数据文件)

wKiom1h784-hwsaTAABZXJt4F08879.png-wh_50

Innodb共享表空间配置:

修改 my.cnf 文件:

wKioL1h786iCy-7lAAHJQVHXVVg267.png-wh_50

参数解释:

innodb_data_home_dir= "/path/" 数据库文件所存放的目录

innodb_log_group_home_dir= "/path/" 日志存放目录

innodb_data_file_path=ibdata1:100M:autoextend设置一个可扩展大小的尺寸为 10MB 的数据

文件(共享数据文件),名为 ibdata1。没有给出文件的位置,所以默认的是在 MySQL 的数

据目录内。

innodb_file_per_table=10 //1 为使用独占表空间,0 为使用共享表空间

注:InnoDB 不创建目录,所以在启动服务器之前请确认”所配置的路径目录”的确存在。

重启 mysqld 服务

wKiom1h7872hp-2pAACzRe7puUI992.png-wh_50

mysqld启动失败,查看错误日志

显示内容如下:

wKioL1h789bAGgHZAAM-8G3lTbw753.png-wh_50

注:不同版本的 mysql 报错略有不同,注意看错误日志的内容。

从错误日志中显示可以看出

/etc/my.cnf 文件中设置 6400 页而当前 ibdata1 768

需要计算 768/64=12

修改配置为

wKiom1h78-qjOOffAAHGowrCJjc680.png-wh_50

重启 mysqld 服务

wKioL1h78_uz3lynAAI0-ievr3E995.png-wh_50

启动 mysql,成功!

注:计算公式:64pages 相当于 1M1page 16KB

如果不清楚默认文件 page 大小,可以先 du -h ibdata1 查看下,再去设置;

wKioL1h79A6j5wiIAABCqD05PII437.png-wh_50

这说明 mysql5.7.13 ibdata 初始化为 12M

登录 mysql 执行 mysql> show variables like '%innodb_file_per_table%';

wKiom1h79CGDmU4EAACBoE3_xpI243.png-wh_50

wKiom1h79DLAHemzAABcjs2VjLQ037.png-wh_50

这时新建的表就会使用共享表空间了。

创建一个数据库 testdb 并新建一个表

wKioL1h79EWBfm0tAABiTYpoHvE921.png-wh_50

向表中插入若干行数据

这里定义一个存储过程向表中插入 100000 行数据

wKioL1h79FfyCNeiAADp-DkLz_w307.png-wh_50

调用存储过程

wKiom1h79HOjHykPAAC3YQXyyn8363.png-wh_50

查看表中行数:

wKioL1h79IbRMbI_AABUi4anKlU114.png-wh_50

如何查看表在表空间占用情况:

方法 1:对 INNODB,你可以直接用命令 show table status 查看某个表的表空间占用情况。

wKiom1h79JyDNbweAAFjgeNM9Q8612.png-wh_50

方法 2

如果想知道 MySQL 数据库中每个表占用的空间、表记录的行数的话,可以打开 MySQL

information_schema数据库。在该库中有一个 TABLES 表,这个表主要字段分别是:

TABLE_SCHEMA: 数据库名

TABLE_NAME:表名

ENGINE:所使用的存储引擎

TABLE_ROWS:记录数

DATA_LENGTH:数据大小

INDEX_LENGTH:索引大小

wKiom1h79LLCBgkxAAEQigxwDkM198.png-wh_50

3 Replication的相关文件:

1master.info 文件:

master.info文件存在于 Slave 端的数据目录下,里面存放了该 Slave Master 端的相关信

息,包括 Master 的主机地址,连接用户,连接密码,连接端口,当前日志位置,已经读取

到的日志位置等信息。

2relay log relay log index

mysql-relay-bin.xxxxxn文件用于存放 Slave 端的 I/O 线程从 Master 端所读取到的 Binary Log

信息,然后由 Slave 端的 SQL 线程从该 relay log 中读取并解析相应的日志信息,转化成

Master所执行的 SQL 语句,然后在 Slave 端应用。

mysql-relay-bin.index文件的功能类似于 mysql-bin.index,同样是记录日志的存放位置的绝对

路径,只不过他所记录的不是 Binary Log,而是 Relay Log

3relay-log.info 文件:

类似于 master.info,它存放通过 Slave I/O 线程写入到本地的 relay log 的相关信

息。供 Slave 端的 SQL 线程以及某些管理操作随时能够获取当前复制的相关信息。

4 、其他文件:

1system config file

MySQL的系统配置文件一般都是 my.cnf,默认存放在"/etc"目录下,my.cnf 文件中包含多种

参数选项组(group),每一种参数组都通过中括号给定了固定的组名,如“[mysqld]”组中

包括了 mysqld 服务启动时候的初始化参数,“[client]”组中包含着客户端工具程序可以读取

的参数。

2pid file

pidfile mysqld 应用程序在 Unix/Linux 环境下的一个进程文件,和许多其他

Unix/Linux服务端程序一样,存放着自己的进程 id

3socket file

socket文件也是在 Unix/Linux 环境下才有的,用户在 Unix/Linux 环境下客户端连接可以不

通过 TCP/IP 网络而直接使用 Unix Socket 来连接 MySQL

mysql有两种连接方式,常用的一般是 tcp

mysqlhmysql 主机 ip -uroot -pxxx

mysql-S/path/mysql.sock

wKioL1h79MugzEC5AAF6da22UWk007.png-wh_50

注:采用 unix socket 连接方式,比用 tcp 的方式更快,但只适用于 mysql 和应用同在一台 PC

上。