进行MySQL的配置优化,首先必须找出MySQL的性能瓶颈所在;而SHOW STATUS输出的报告正是用来计算性能瓶颈的参考数据。mysqlreport不像SHOW STATUS那样简单的罗列数据,而是对这些参考数据加以融合计算,整理成一个个优化参考点,然后DBA就可以根据这个优化参考点的值以及该点的衡量标准,进行对应调整。在分析报告中有好多没有完整的说明因此就写了这篇博文。些翻译不对的。请及时和我联系或留言。

mysqlreport主页和下载地址
web site:http://hackmysql.com/mysqlreport
download:http://hackmysql.com/scripts/mysqlreport-3.5.tgz

mysqlreport的安装极为简单,下载上述文档后,使用tar -xvf mysqlreport-3.5.tar解压后,在当前目录生成文件夹mysqlreport-3.5,该文件夹下的mysqlreport即是可执行程序。
注意:mysqlreport为perl脚本,用到DBI以及DBD::mysql,须正确安装后才能正常使用!

# ./mysqlreport --help

mysqlreport v3.5 Apr 16 2008

mysqlreport makes an easy-to-read report of important MySQL status values.

Command line options (abbreviations work):

  --user USER       Connect to MySQL as USER

  --password PASS   Use PASS or prompt for MySQL user's password

  --host ADDRESS    Connect to MySQL at ADDRESS

  --port PORT       Connect to MySQL at PORT

  --socket SOCKET   Connect to MySQL at SOCKET

  --no-mycnf        Don't read ~/.my.cnf

  --infile FILE     Read status values from FILE instead of MySQL

  --outfile FILE    Write report to FILE

  --email ADDRESS   Email report to ADDRESS (doesn't work on Windows)

  --flush-status    Issue FLUSH STATUS; after getting current values

  --relative X      Generate relative reports. If X is an integer,

                    reports are live from the MySQL server X seconds apart.

                    If X is a list of infiles (file1 file2 etc.),

                    reports are generated from the infiles in the order

                    that they are given.

  --report-count N  Collect N number of live relative reports (default 1)

  --detach          Fork and detach from terminal (run in background)

  --help            Prints this

  --debug           Print debugging information

Visit http://hackmysql.com/mysqlreport for more information.
选项    解释
- -user    连接MySQL的用户名
- -password    连接MySQL的用户密码。命令行上出现该选项但没有给出参数时,mysqlreport将在用户回车后提示输入密码
- -host    MySQL服务器地址
- -port    MySQL服务器的开发端口
- -socket    本地MySQL UNIX域套接口路径
- -no-mycnf    该选项指引mysqlreport不要读取 ~/.my.cnf,默认情况下会去读取这个文件。- -user 和 - -password 总是覆盖从 ~/.my.cnf 中取得的参数
- -infile    从status文件读取数据,代替从服务器上读取
- -outfile    打印报告后,将报告同时写入该选项指定的文件中。mysqlreport 的内部机制总是先将报告写入临时文件中,然后将该临时文件里的内容打印到屏幕上。如果指定了- -outfile选项,则将临时文件拷贝成 指定的文件。如果指定了选项- -email,则会删除临时文件
- -email    打印报告后,将结果发送到指定的邮箱。该选项需要使用/usr/sbin/目录下的sendmail程序,因此无法在windows 平台下使用。/usr/sbin/sendmail可以符号链接到 qmail,或者任何其他能模拟sendmail -t方式的MTA程序。邮件来源是:mysqlreport,主题是:MySQL status report on HOST,HOST是mysqlreport所在的主机名,可能是读取到的- -host值,默认是localhost
- -flush-status    打印报告后,运行FLUSH STATUS命令
- -relative    mysqlreport通常产生从MySQL启动以来的状态报告。指定- -relative选项可产生相对于前次报告以来的相关报告。

如果选项参数是一个整数,程序每隔指定的秒数后再次产生一份状态报告,报告次数由- -report-count选项指定。默认产生1份相关报告。例如,指定- -relative的值为60,则会产生2份报告:第一份基本报告马上生成,第二份相关报告在60秒后生成。第二份报告中的数值和前面的那份相关。例如,前者总共有10.00k次查询,在这60秒的间隔时间里接受了新的1.00k次查询,则后者的总查询次数是1.00k而非11.00k次。

如果选项参数是本地文件列表(就像- -infile选项那样),程序会按照参数中文件的顺序来依次产生状态报告。文件列表中的文件应该以空格分隔。以文件产生时间依次排列文件就显得很重要,较早产生的文件应该放在列表的前面。第一个文件中必须有系统变量,例如:key_buffer_size、table_cache 等。每个文件中可以有多组”SHOW STATUS”的结果。注意:通过 “mysqladmin -r -i N extended” 产生的状态文件无法使用,因为 mysqladmin的-r参数已经令其产生了具有相对性的状态值了。

由于mysqlreport首先会把状态报告写到临时文件中,如果- -relative的参数是整数时,mysqlreport会显示它把文件写到哪了。那么就可以直接通过查看这些文件内容来观察服务器的状况
- -report-count    生成N份相关的报告。本选项只有在同时启用- -relative选项后才有效。mysqlreport会自动产生N+1份报告:第一份基本报告,以及后面的N份相关报告
- -detach    本选项使得mysqlreport派生新进程,从终端上脱离转入后台继续运行。派生新进程后,mysqlreport 会报告它把结果写入了哪个临时文件。本选项需要- -outfile或- -email中的一个,如果这两个选项都没有给出,则产生的临时文件就会被删除,因为自派生出新进程后,无法再将结果打印到终端屏幕上了。本选项如果和- -relative选项一起使用的话就更有意义了,这样mysqlreport就能定时报告信息,而无需人工干预获得报告。例如使用如下命令,就能让mysqlrepot隔一个小时再次产生一次报告,并将结果发送到指定的信箱:perl mysqlreport - -relative=3600 - -detach - [email protected]。一个小时候后,mysqlreport通过email发送报告,删除临时文件,并且干净地终止
- -help    打印帮助信息
- -debug    打印调试信息

使用mysqlreport的简单例子

1.连接远程数据库192.168.12.14

perl mysqlreport - -host=192.168.12.14 - -user=db_user - -password=db_user_password

2.通过本地UNIX域套接口文件/data/mysql_data/mysql.sock连接本地数据库

perl mysqlreport - -user=root - -password=root_password - -socket=/data/mysql_data/mysql.sock

3.将输出报告写入文件/data/mysql_data/report/mysqlreport.txt

perl mysqlreport - -user=root - -password=root_password - -socket=/data/mysql_data/mysql.sock - -outfile=/data/mysql_data/report/mysqlreport.txt

报告说明

MySQL 5.0.3              uptime 0 0:34:26       Fri Sep  1 19:46:02 2006

  2

  3 __ Key _________________________________________________________________

  4 Buffer used   380.00k of 512.00M  %Used:   0.07

  5   Current      59.32M            %Usage:  11.59

  6 Write hit      97.04%

  7 Read hit       99.58%

  8

  9 __ Questions ___________________________________________________________

 10 Total          98.06k   47.46/s

 11   DMS          81.23k   39.32/s  %Total:  82.84

 12   QC Hits      16.58k    8.02/s           16.91

 13   COM_QUIT        200    0.10/s            0.20

 14   Com_            131    0.06/s            0.13

 15   -Unknown         82    0.04/s            0.08

 16 Slow 5 s            0    0.00/s            0.00  %DMS:   0.00  Log:  ON

 17 DMS            81.23k   39.32/s           82.84

 18   SELECT       64.44k   31.19/s           65.72         79.33

 19   INSERT       16.75k    8.11/s           17.08         20.61

 20   UPDATE           41    0.02/s            0.04          0.05

 21   REPLACE           0    0.00/s            0.00          0.00

 22   DELETE            0    0.00/s            0.00          0.00

 23 Com_              131    0.06/s            0.13

 24   change_db       119    0.06/s            0.12

 25   show_fields       9    0.00/s            0.01

 26   show_status       2    0.00/s            0.00

 27

 28 __ SELECT and Sort _____________________________________________________

 29 Scan               38    0.02/s %SELECT:   0.06

 30 Range              14    0.01/s            0.02

 31 Full join           3    0.00/s            0.00

 32 Range check         0    0.00/s            0.00

 33 Full rng join       0    0.00/s            0.00

 34 Sort scan          14    0.01/s

 35 Sort range         26    0.01/s

 36 Sort mrg pass       0    0.00/s

 37

 38 __ Query Cache _________________________________________________________

 39 Memory usage   17.81M of  32.00M  %Used:  55.66

 40 Block Fragmnt  13.05%

 41 Hits           16.58k    8.02/s

 42 Inserts        48.50k   23.48/s

 43 Prunes         33.46k   16.20/s

 44 Insrt:Prune    1.45:1    7.28/s

 45 Hit:Insert     0.34:1

 46

 47 __ Table Locks _________________________________________________________

 48 Waited          1.01k    0.49/s  %Total:   1.24

 49 Immediate      80.04k   38.74/s

 50

 51 __ Tables ______________________________________________________________

 52 Open              107 of 1024    %Cache:  10.45

 53 Opened            118    0.06/s

 54

 55 __ Connections _________________________________________________________

 56 Max used           77 of  600      %Max:  12.83

 57 Total             202    0.10/s

 58

 59 __ Created Temp ________________________________________________________

 60 Disk table         10    0.00/s

 61 Table              26    0.01/s    Size:  4.00M

 62 File                3    0.00/s

 63

 64 __ Threads _____________________________________________________________

 65 Running            55 of   77

 66 Cache               0              %Hit:    0.5

 67 Created           201    0.10/s

 68 Slow                0    0.00/s

 69

 70 __ Aborted _____________________________________________________________

 71 Clients             0    0.00/s

 72 Connects            8    0.00/s

 73

 74 __ Bytes _______________________________________________________________

 75 Sent           38.46M  18.62k/s

 76 Received        7.98M   3.86k/s

 77

 78 __ InnoDB Buffer Pool __________________________________________________

 79 Usage           3.95M of   7.00M  %Used:  56.47

 80 Read hit       99.99%

 81 Pages

 82   Free            195            %Total:  43.53

 83   Data            249                     55.58 %Drty:   0.00

 84   Misc              4                      0.89

 85   Latched           0                      0.00

 86 Reads         574.56k     0.6/s

 87   From file       176     0.0/s            0.03

 88   Ahead Rnd         4     0.0/s

 89   Ahead Sql         2     0.0/s

 90 Writes        160.82k     0.2/s

 91 Flushes         1.04k     0.0/s

 92 Wait Free           0       0/s

 93

 94 __ InnoDB Lock _________________________________________________________

 95 Waits               0       0/s

 96 Current             0

 97 Time acquiring

 98   Total             0 ms

 99   Average           0 ms

 100  Max               0 ms

 101

 102 __ InnoDB Data, Pages, Rows ____________________________________________

 103 Data

 104   Reads           225     0.0/s

 105   Writes          799     0.0/s

 106   fsync           541     0.0/s

 107   Pending

 108     Reads           0

 109     Writes          0

 110     fsync           0

 111

 112 Pages

 113   Created          23     0.0/s

 114   Read            226     0.0/s

 115   Written       1.04k     0.0/s

 116

 117 Rows

 118   Deleted      25.04k     0.0/s

 119   Inserted     25.04k     0.0/s

 120   Read         81.91k     0.1/s

 121   Updated           0       0/s

Line 1

   报表的第一行包含了三样不同的资讯:MySQL Server 的版本、自上次啟动后已经过多少时间、目前 Server 的日期与时间。有些人会定时让系统自动产生报表(eg. cron)然后用程序去分析进行分析,此时表头将可用来协助您辨识出不同时间点的报表。对於那些租用或使用虚拟主机的管理者,表头可以协助您了解自己所需面对的是什么样的 Server。MySQL Server 版本可以指出该 Server 有提供或没有提供那些功能,而它的 Uptime 则表示该报表具有多大的代表性。Uptime 是重要的指标,可让您了解此份报表所包含的资讯是否可能有偏误,一般来说 Uptime 最少要有一小时会比较适当,甚至光是一小时其实也还不够。例如您的 Server 可能已执行了六个小时,但此六小时皆是在使用率最低的午夜,此时产生出的报表就很不具有代表性。最理想的情况下,你会希望 MySQL Server 至少已经执行了一整天,这样子一来你就可以确定报表中的资讯已包含了 Server 负载的高峰与低峰期,而不是只包含其中之一。在范例报表中 Server 只执行了 34 分鐘,因此该报表的代表性是不足的,但因为这只是用来做范例,也就没什么关係。

Key Report: Lines 3 - 7

   第一个主要报告区块就是 Key Report,因为 Key(Indexes, 索引)是所有资讯中最重要的一项。虽然此报表无法告知您 Server 是否有善用 Index,但它可以告诉您 Server 对於 Shared Key Buffer 的使用状态。请注意,这里所指的 Key Buffer 是指 MyISAM Storage Engine 所使用的 Shared Key Buffer,InnoDB 所使用的 Key Buffer 并不包含在内。

   MySQL Server 支援许多种不同类型的资料表(比较正式的说法是 Storage Engine),你可以将它们想像为各种不同的资料结构,而不同的 Storage Engine 各有其优缺点。其中 MySQL Server 预设是使用 MyISAM Storage Engine。

   MySQL Server 的 Buffer 大略可分为二种:

   1. Global Buffer:由所有 Client 所共用的 Buffer

       key_buffer

       innodb_buffer_pool

       innodb_log_buffer

       innodb_additional_mem_pool

       net_buffer ...等等

   2. Thread Buffer:个别的 Connection 所需佔用的 Buffer

       例如:

       sort_buffer

       myisam_sort_buffer

       read_buffer

       join_buffer

       read_rnd_buffer ...等等

   计算 Server 至少需使用的总记忆体数量的方式为:

   min_memory_needed = global_buffer + (thread_buffers * max_connection)

   关於 MySQL 的 Cache 机制有一点需要特别注意,各位应该都知道 MyISAM Storage Engine 将每个 table 分成三个档案储存在硬盘之中,例如若您有一个资料表的名称为 example,那么您就会在硬盘上发现 example.FRM, example.MYD, example.MYI 等三个档案。这三个档案所储存的资料如下:

       FRM: 储存这个资料表的结构

       MYD: Row Data,也就是你存在 example 资料表里的资料

       MYI: 此资料表的索引

   接下来是重点:

   当 MySQL 要 Cache 某个资料表时,请问 MySQL 会 Cache 哪些资料?

   答案是:

   MySQL 只会 Cache 索引,也就是 *.MYI 档案,而 Row Data(*.MYD) 则是交由作业系统来负责 Cache。

   接下来我们再回到 Key Buffer,有个很重要的问题我们一直没有回答,就是『到底 Key Buffer 要设定多少才够呢?』。如前所述,MySQL 只会 Cache 索引(*.MYI),因此您只要将资料库中所有的 MYI 档案加总起来,你就会知道大概要设为多少。

Buffer used: Line 4

   身为 MySQL 的管理者您通常会问的第一个问题是:『Server 到底用掉了多少 key buffer?』。如果您发现 MySQL 只使用了一小部份的 Key Buffer,这并不是什么需要注意的问题,因为 MySQL 只会在需要的时候才实际分配与使用 System RAM。也就是说,当你设定 MySQL 可使用 512MB 的 RAM 时,并不代表 MySQL 啟动的时候将佔用 512MB 的 RAM(只有在 MySQL 认为需要这么做的时候才会)。报表中的第四行(Buffer used)指出 MySQL "曾经" 耗用过的最大记忆体数量,因此目前 "正在使用" 的记忆体数量有可能少於(甚至大於)这个数字。MySQL 称此数值为 "High Water Mark",但在报表的下一行我们将会看到它并不总是如此。无论如何,从 Buffer used 我们通常可以看出 key_buffer_size 这个系统变数值是否设定的够大,如果你的 MySQL 已经使用了 80~90% 以上的 Key Buffer,你就应该要调高 key_buffer_size。注意,Buffer used 永远不会有使用率超过 95% 的情况,因为 MySQL 的官方文件中指出 Share Key Buffer 中有部份将会挪用给内部资料结构使用,因此当 Buffer used 指出 Share Key Buffer 的使用率高达 95% 时,其实在实务上等於是已使用了 100% 的 Share Key Buffer。在这个例子中 Server 只使用了 380KB(0.07%) 的 Share Key Buffer,看到这里也许您会判断 Server 的 Share Key Buffer 是十分充足的,但请勿太早下定论,我们必须要接著考量报表中的下一行才能做出客观的判断......。

Current: Line 5

   mysqlreport 使用 Key_blocks_unused 这个系统变数来决定目前 MySQL "正在使用" 的 Share Key Buffer 大小,只有在 MySQL Server 4.1.2 以上的版本才会有这个功能。如果报表中的上一行(Buffer used)真的有如 MySQL 官方文件中所说的是 "High Water Mark",那么 Current 所载明的数值应该永远会小於或等於它。但在接下来的例子中我们将会看到,事情并不总是如此。目前这台 Server 已经使用了大约 60MB(12%) 的 Share Key Buffer,这是一个好现象因为它代表了你的 Share Key Buffer 仍然十分充足。Current 与 Buffer used 合在一起看即可提供一个很有用的指标,告诉您目前的 key_buffer_size 是否充足。

   设定 key_buffer_size 的方式也很简单,只要直接修改 MySQL 的设定档然后重新啟动 Server 即可。例如若要将 Key Buffer 设定为 2000MB,则只要在 /etc/my.cnf 中加上:

   [mysqld]

   key_buffer_size=2000M

Write ratio: Line 6

   索引(Indexes, Keys)主要是在记忆体内(RAM-Based)进行操作的,索引之所以如此有用有部份原因就归功於它们主要是在 RAM 里面运作,因此拥有极高的存取性能,不像储存在硬盘中的资料存取速度非常慢。然而,不可否认的是 MySQL 终究还是必须从硬盘中将索引读入 RAM 或是将储存在 RAM 中的索引写回硬盘之中。Write ratio 标示著 MySQL 将索引写入硬盘与 MySQL 将索引写入 RAM 的比值(Write Ratio = MySQL 将索引写入硬盘的次数 / MySQL 将索引写入 RAM 的次数)。具有接近於 1 的 Write Ratio 并不是一件很罕见的事,就像 MySQL 官方手册中所说的,如果你的 MySQL 最主要的活动是 Update、Insert 等等,那么 Write Ratio 将会很接近於 1。Write Ratio 若大於 1 表示 MySQL 将索引写入硬盘的次数大於将索引写入 RAM 的次数,很少有 MySQL Server 的 Write Ratio 会大於 1,绝大部份都应该会小於 1,即便是负载非常重的 Server。

Read ratio: Line 7


   Read Ratio 比 Write Ratio 来得重要一些,它标示了 MySQL 从硬盘读取索引与从 RAM 读取索引的比值(Read Ratio = MySQL 从硬盘读取索引的次数 / MySQL 从 RAM 读取索引的次数)。Read Ratio 的值应该要是 0.00 或 0.01,若大於这个值则表示 Server 有问题需要进一步的调查,通常此问题的成因是 Share Key Buffer 设得太小造成 MySQL 需要不断地从硬盘中读取所需要的索引资讯,而这个动作是十分没有效率的并且完全抵消了使用索引可以带来的好处。在 Server 刚啟动的头一个小时 Read Ratio 很常会出现大於 0.01 的数值,但 Server 执行过一阵子后它应该(也必须)降低至 0.01 或是 0.00。

Questions Report: Lines 9 - 26


   第二个主要的报表区块,Questions,是第二重要的资讯,因为它可以告诉你 MySQL 到底都在忙些什么事情。Questions 包含了 SQL queries 以及 MySQL protocol communications。大部份的人都只在意 Server 每秒可以处理多少查询(Queries Per Second, QPS),但若以整个 Server 的观点来考量,QPS 其实是非常不精确的数值,它无法有效的告诉您 Server 的整体运作状况。而 Questions 则提供了较完整的资讯,让您一窥 Server 的全貌。

Total: Line 10

   第一个栏位单纯的记载 MySQL 总共回应过多少查询,第二个栏位则记录回应的频率(QPS),当大部份的人说『我的 Server 平均每秒处理 XXX 个查询』时,他们指的其实就是第二个栏位所记录的回应频率。此时你应该要反问他们『在那 XXX 个查询之中,MySQL 到底做了哪些事情?』,接下来 mysqlreport 将可以协助您回答此问题......。

Distribution of Total Queries (DTQ): Lines 11 - 15


   所有的 Questions 可以大致区分为五个不同的类别:

   1.Data Manipulation Statements (DMS)

   2.query cache hits (QC Hits)

   3.COM_QUIT

   4.all other Com_ commands

   5.Unknown

   这五个类别将会展示在 Lines 11 至 15,但它们的顺序是会改变的。mysqlreport 预设是以查询的总数(第一个栏位)来排序,次数越多排得越上面,让您可以快速的分辨出 MySQL 大部份时间都在忙些什么东西。理想的情况下,你会希望 MySQL 把大部份的时间都花在 DMS 与 QC Hits 这两个类别,因为这两个类别才是真正在 "完成正事" 的类别。COM_QUIT、Com_、与 Unknown 也有其存在的必要,但它们应该只佔了其中的一小部份。在继续深入介绍之前,也许你会好奇第三个栏位是做什么用的,它代表了该分类(例如 DMS)佔全部 Queries 的百分比;若是在子分类(例如 Select)中,则表示该子分类佔所属分类(例如 DMS)的百分比。在此范例中 DMS 佔了所有 Queries 的 82.84%,这是一个很好的现象。

   Data manipulation statements(DMS) 包含了:ELECT, INSERT, REPLACE, UPDATE, 与 DELETE(技术上来说,其实不只这几个类别但 mysqlreport 只会用到这几类)。基本上,你可以将 DMS 想成是 MySQL 真正有在做些 "有用的事" 的情况,因此你会希望 DMS 是 MySQL 最忙著处理的事情。

   QC Hits 是 MySQL 不需要实际执行 Query 而只要直接从 Query Cache 中即可找到所需资料的次数。拥有高比例的 QC Hits 是让人梦寐以求的事,因为从 Query Cache 直接存取所需要的资料是十分快速且有效率的。然而大部份的 MySQL Server 因为各种原因,而无法具有非常有效率的 Query Cache。在本范例中 QC Hits 佔了所有 Questions 的 16.91%,这是非常好的情况。然而,千万不要被这个数值给误导了,在报表中的 38 至 45 行(Query Cache Report)将会告诉您完全不同的状况。这是一个很好的范例,展示了 mysqlreport 可以做为深入、相互参照与比对的分析工具。当 QC Hits 看来似乎十分完美时,这个 Server 的 Qeury Cache Report 却可以明确的告诉您其实事情没有表面上看起来的那样完美,我们在稍后会在回到这个问题。


   COM_QUIT 算是比较不重要的类别,若您不是真的很有兴趣其实您大可忽略这个类别的内容。

   COM_这个类别代表著所有 MySQL 所执行过的指令,通常与 MySQL protocol 相关。在正常的情况下,你会希望这个类别所佔的比例越低越好,因为当这个数值很高的时候就表示 MySQL 正忙碌於无关紧要的事情上。若这个数值很高通常代表 MySQL 正遭遇到某些很奇怪的问题,当我们深入讨论 COM_ 的子类别的时候,我们会在回来探讨这个问题。

   Unknown 是推论出来的类别,在理想的状况下,之前所述的四个分类加总起来应该要等於 Questions 总数,但它们通常不会刚好等於。这是因为有些 Questions MySQL 在处理时会增加 Total Questions 的计数器,但却没有相对应的系统变数用来记录所执行过的 Questions。在不同的 Server 上这个数值的变异很大,在有些 Server 上这个数值非常的高,在有些 Server 上则非常的低,但在大部份的情况下它应该要维持在很低的水準才是。如果这个数值非常的高,可能代表 MySQL Server 有什么地方出了问题。

Slow: Line 16


   第 16 行非常的重要:它记录了 MySQL 总共执行了多少次 Slow Query。Slow Query 就是指执行所需时间超过某个时间区间的 Query,例如执行超过 10 秒的 Query。用来判定是否为 Slow Query 的时间区间是可以透过 long_query_time 这个系统变数来设定的,MySQL 预设 long_query_time 为 10 秒,但通常我们会将它设定为 5 秒。在最理想的情况下,我们会希望看到这个数值等於零,但通常这数值不会是零。一般来说 Slow Query 佔 Total Questions 的比例应该要低於 0.05,Slow Query 的次数(第一个栏位)本身不是很重要,真正需要注意的是 Slow Query 佔 Total Questions 的比例,若这比例偏高就代表 Server 有些问题需要解决。第四个栏位中的『%DMS: 』表示 Slow Query 在所有 DMS 中所佔的比例。

DMS: Lines 17 - 22

   DMS 的子分类项目可以告诉我们,这台 MySQL Server 是属於哪一个类型的 MySQL Server,例如它是著重在 SELECT 操作或是 INSERT 操作,大部份的 MySQL Server 都是著重在 SELECT 操作。知道某台 Server 是属於哪一个类型的 MySQL Server 有助於我们思考报表中的其他资讯,例如一台著重在 SELECT 操作的 MySQL Server 的 Write Ratio 应该会非常的接近 1,并有著较高的 Lock 时间。同时它也隐含了一个意义,就是也许你可以考虑使用 InnoDB Storage Engine,因为 MySQL 预设採用的 MyISAM Storage Engine 所提供的 Lock 层级只有 Table Lock(只能针对整个资料表锁定),而 InnoDB 则提供 Row Lock 层级的锁定机制(可只针对特定的 ROW 进行锁定,减少等待时间)。若是著重在 SELECT 操作的 Server,它的 Read Ratio 应该会接近於零,并有著非常低的 Table Lock 时间。

   在范例中的 Server 是属於著重在 SELECT 操作的 Server:65.72% 的 Questions 是 SELECT(第三个栏位)、79.33% 的 DMS Questions 是 SELECT(第四个栏位)。很明显的,这是台著重在 SELECT 操作的 Server,知道了此项事实之后,我们才有办法对其进行最佳化。

Com_: Lines 23 - 26

   这个子分类只有在它的值偏高的时候才需要注意,因为过高的值表示 MySQL 正在忙著处理 "程序方面的东西",而不是回应使用者的查询。对大部份的 Server 来说这里应该都不会出现偏高的数值,但您最好还是定期的检查一下。

SELECT and Sort Report: Lines 28 - 36


   大致上来说,你只要注意第 29 行与第 31 行:Scan 与 Full Join。Scan 指的是有多少 SELECT statements 造成 MySQL 需要进行 Full Table Scan。Full Join 的意思与 Scan 差不多,但它是适用在多个 Tables 相互 Join 在一起的情况。这二种情况的执行性能都非常的差,因此原则上你会希望这两个数值越低越好。但这也不是绝对的,仍然要考虑实际的情况,例如虽然 Server 有很高比例的 Scan,但若这些 Scan 都是针对一些只有几十笔资料的 table,那么相对而言它依然是十分有效率的;但反之,若这些 Scan 是针对具有上百万笔资料的 table,那么就会严重影响系统性能。

Query Cache Report: Lines 38 - 45


Query Cache Report 只有在 MySQL 有支援 Query Cache,以及 Query Cache 功能有开啟的情况下才会有这段资讯出现。

Memory usage: Line 39

   此项目指出 Query Cache 的使用状况,若系统已达到 Query Cache 的上限则会连带影响到 Prunes Value,因为当配给的 Memory 不足时,MySQL 必须不断地消除 RAM 中较不常使用的资料以挪出空间摆放新的资料。

Block Fragmnt: Line 40

   这个数值越高表示 Query Cache 的 Fragment 状况越严重,通常它会界於 10%~20% 之间。在此范例中 Block Fragmnt 为 13.05%,这是可接受的情况,当然你也可以调整 query_cache_min_res_unit 的值来降低 Block Fragmnt。

Hits, Inserts, Prunes: Lines 41 - 43


   Hits 是这三个数值中最重要的一项,因为它指出有多少 SELECT statements 是可直接从 Query Cache 里面取得所需的资讯,此数值越高就越好。Inserts 和 Prunes 最好是从第 44 行的比值来观察比较容易理解。虽然 Prunes 的值偏高可能代表著 Query Cache 设得不够大,但并不一定是如此。在本例中只有 55% 的 Query Cache 被使用,有著相对而言算低的 fragmentation 值,但 Prunes 值偏高,Prunes 的值(16/s)是 QC Hits 的两倍。你可以想像这台 Server 的 Query Cache 是一颗苹果树,它的树枝被剪去的速度比你採收苹果的速度还快。

Insrtrune and Hit:Insert Ratios: Lines 44 - 45


   第 44 行中的 Insert 与 Prune 的比值可显示 Query Cache 的挥发性。在一个高度稳定的 Query Cache 中,Insrt 的值应该要高於 Prune 的值;反之,在一个挥发性较高(较不稳定)的 Query Cache 中,这个比值将会是 1:1 或是偏重在 Prune 那方,这表示 Query Cache 中的资料有可能在使用到之前就已经被清除了。我们会希望拥有一个稳定的 Query Cache,因为稳定的 Query Cache 表示那些被 Cache 在 Query Cache 中的资料会常被用到。高挥发性(较不稳定)的 Query Cache 代表两件事情:第一,Query Cache 设得太小,需要加大。第二,MySQL 正试图要 cache 所有的东西,甚至是那些其实并不需要 cache 的资料。若是第一种状况,只要单纯的加大 Query Cache 即可。若是第二种情况,可能是 MySQL 试图要去 cache 所有可以 cache 的资料,你可以使用 SQL_NO_CACHE 来明确的告诉 MySQL 什么资料是你不想要 cache 的。

   Hit 与 Insert 的比值代表著 Query Cache 的有效性,理想的情况是我们新增了一些 Qeury 到 Query Cache 中,然后希望得到许多 Hits。因此若是这个 Query Cache 是有效率的,那么该比值应该要偏重在左方。若比值是偏重在 Insert 那方,那么这个 Query Cache 的挥发性就太高了。考虑以下这个比值,若 Hit:Insert 为 1:1,那就表示 Query Cache 中的资料只使用了一次就被清除掉了,换句话说,我们放进去的资料比我们从里面拿出来的资料还多,这样一来就失去了使用 Query Cache 的意义。回想我们前面所提过的,虽然在本范例中 QC Hit 在全部的 Questions 中佔了很高的比例,但实际上我们可以发现 QC 的有效性其实是很低的(Hit:Insert 的比值偏重在 Insert 那方)。若造成这个现象的原因是 MySQL 正试图 cache 所有的东西,那么将 Cache 模式改为 DEMAND 或许可以解决此问题。

Table Locks Report: Lines 47 - 49


   这个部份包含了两项资讯:第一项是 Waited,代表 MySQL 需要等待以取得 table lock 的次数。第二项是 Immediate,表示 MySQL 不需要等待即可立刻取得 table lock 的次数。对资料库来说『等待』几乎可以肯定是一件很不好的事情,因此 Waited 的值应该要越小越好。最具有代表性的是第三个栏位(Waited 佔所有 table lock 的百分比),这个数值应该要小於 10%,大於这个值就表示 table/query 的索引设计不良或是有过多的 Slow Query。

Tables Report: Lines 51 - 53


   Tables Report 同样包含了二项资讯:第一是 Open,显示目前正开啟的 table 数量、总共可开啟的最大数量,以及 Table Cache 的使用状况。第二是 Opend,表示截至目前为止 MySQL 总共开啟过的 Table 数量,以及除上 Uptime 后的比值。这里有两件事值得注意:首先是 Table Cache 的使用状况,100% 的 Table Cache 使用率并不是一件坏事但你可以试著调大 Table Cache 以增进性能。第二是 MySQL 开啟 Table 的平均速率,若这个值很高则表示您的 table_cache 设得太小了,需要调大一些。一般来说,MySQL 开啟 Table 的平均速率最好是小於 1/s。但大於这个数值也不一定就是坏事,有些调校良好且运作的十分有效率的 MySQL Server 其值为 7/s 并使用了 100% 的 Table Cache。

Connections Report: Lines 55 - 57

   Connections Report 所代表的意义与 Tables Report 相似,请各位以此类推。比较需要注意的是:若你发现 Connections 的使用率接近 100%,也许你会想调大 max_connections 的值以允许 MySQL 的 Client 建立更多连线。然而,这通常是一种错误。我们常常可以发现很多网路上的资料会教我们要调大 max_connections,但却从来没有给一个明确的理由。事实上,max_connections 的预设值(100),就算是对於负载十分沉重但有良好调校过的 Server 都已十分足够。MySQL 对於单一连线的资料处理通常只需要零点几秒的时间即可完成,就算是最大只能使用 100 个连线也够让你用上很长一段时间。若是您的 Server 有著非常高的最大连线数(max connections)或是单一连线需要很长时间才可完成,那么问题八成不是 max_connections 的值不够大而是在别的地方,例如 slow queries、索引设计不良、甚至是过於缓慢的 DNS 解析。在您将 max_connections 的值调到 100 以上之前,您应该要先确定真的是因为 Server 过於忙碌而需要调高此数值,而不是其他地方出了问题。每秒平均连线数有可能会很高,事实上,若这个值很高而且 Server 的运作十分顺畅,那么这通常会是一个好现象,无需担心。大部份 Server 的每秒平均连线数应该都会低於 5/s。

Created Temp Report: Lines 59 - 62


   MySQL 可以建立暂时性的资料表,它可建立在硬盘中、档案里、或是 RAM 之中,而 Created Temp Report 则提供了相关的数据供您参考。这些数据大多是相对而言,没有一定的标準,但将暂时性的资料表建立在硬盘中是十分没有效率的,因此 Disk table 的值最好是三者中最小的一个。当暂时性的资料表被建立在硬盘中,表示此资料表没有办法被放进 RAM 里面(因为 tmp_table_size 的值设得不够大)。

Threads, Aborted, Bytes Reports: Lines 64 - 76


   这几个部份大多没什么好解释的,只有一个项目值得特别说明:第 66 行的最后一个栏位(%Hit)。每一个连接到 MySQL 的连线都是由不同的 Thread 来处理,当 MySQL 啟动时会预先建立一些 Threads 并保留在 Thread Cache 中,如此一来 MySQL 就不用一直忙著建立与删除 Threads。但当每秒最大连线数大於 MySQL 的 Thread Cache 时,MySQL 就会进入 Thread Thrash 的状态:它不断地建立新的 Threads 以满足不断增加的连线的需求。当 Thread Thrash 发生时,%Hit 的数值就会降低。在本范例中 %Hit 的值为 0.05%,这是非常不好的,因为它表示几乎每一个新进来的连线都会造成 MySQL 建立新的 Thread。我们可以看到在此范例中造成此现象的原凶就在第 66 行的第一个栏位,我们可以发现 Thread Cache 的值为 0,因此 thread_cache_size 的值需要调大。

   话说回来,究竟 %Hit 接近於零真的有什么关係吗?Jeremy Zawondy 曾在部落格上说到:Thread caching 并不是我们最需要关心的问题,但当你解决了所有其他更严重的问题之后,它就会是最严重的问题。(hread caching really wasn't the worst of our problems. But it became the worst after we had fixed all the bigger ones.)


InnoDB Buffer Pool Report: Lines 78 - 92

InnoDB的报告,后续加入的mysqlreport V3.0。仅可在MySQL5.0.2版及更高版本在Innodb_状态值(在SHOW STATUS;)。因此,mysqlreport可能不会显示,即使MySQL正在运行的InnoDB存储引擎InnoDB的这些报告。简而言之:mysqlreport的InnoDB只报告与MySQL5.0.2版和更高版本。


InnoDB存储引擎的一个主要功能是在InnoDB的缓存表数据和索引缓冲池。在内部,缓冲池是由包含不同类型的数据16Kb的页面。 InnoDB的缓冲池报告包含关于在缓冲池中的页数值。

注:我还没有看够mysqlreports从MySQL服务器都是版本5.0.2或更高版本以及InnoDB的严重依赖。因此,覆盖了InnoDB的报告导似乎不是覆盖以前的报告导那么彻底。尽管MySQL V5一直GA版本一段时间了,这是多么惊人共同V4.0和V4.1仍然是。


Usage: Line 79


在79行,InnoDB缓冲池使用类似于在4行主要缓冲区使用。然而,MyISAM引擎只存储在其关键的缓冲区(因此得名)索引,但InnoDB引擎索引存储在缓冲池中的其他数据。因此,这条线显示了缓冲池的多被使用,但它并没有显示什么占的用法。为了得到一个什么样占缓冲池使用一个想法,我们必须看行81至85。

很显然,我们必须避免耗尽的缓冲池空间。与MyISAM引擎,运行的关键缓冲空间可能只导致性能问题(因为表索引的不利影响)。随着InnoDB引擎,运行的缓冲池空间可能会导致更多的问题,因为几乎所有依赖于缓冲池。它可以配置一个自动扩展的缓冲池。



Read hit: Line 80


InnoDB的缓冲池命中读取很相似,主要阅读命中第7行。然而,由于InnoDB的存储超过在缓冲池中只是索引,这个值就比较一般了,然后重点阅读命中的缓存。

InnoDB的缓冲池命中读取指示缓冲池的页读取(被缓存)从RAM(每一行从硬盘读取)的百分比。因此,这一比例应该是非常接近100.00%。在大多数情况下,这个比例为>99.98%。


Pages: Lines 81 - 85


这些行是一个非常完整的进入缓冲池的内容。每一行(82 - 85)对应于不同种类的缓冲池的页:空闲页(82行),数据页(83)- 各类页(84),和“锁定”页(85)。

空闲页的描述。最右侧的列中,“%合计:”,表明多大比例的所有缓冲池页都是空闲的(或数据,其他项,并锁定相应)。此行是79行的相反:不要说有多少是用于缓冲池(79行)这一行怎么表示的缓冲池的多少是空闲的。

数据页的描述。目前还没有方法知道的各种数据,这些页包含。此行有一个额外的列:%DRTY(%脏页)。此列表示多少百分比的数据页已被修改(脏),但是还没有被刷新/保存到硬盘。

没有太多可以说的剩下的两个的页类型:其他项和锁定。至于其他项页,MySQL手册只是说:“那是繁忙的,因为它们已经被分配用于行政开销,如行锁或适应哈希索引页面的数量。”至于锁定页:“这些都是页正在读取或写入或无法刷新或删除某些其他原因。”


Reads: Lines 86 - 89


下面四行给出一些指示InnoDB的缓冲池的阅读活动。第一行,第86行,简直池从RAM中读出缓冲器的数量的度量。在使用InnoDB的繁忙的服务器,这个值应该是很高的,因为InnoDB的读数应为大部分页面从RAM中的缓冲池。此指标可以被认为的InnoDB缓冲池吞吐量的度量。由于几乎所有的InnoDB需要保持并从缓冲池中取出,缓冲池读取应尽可能快。例如,一个InnoDB缓冲池读取速度超过200K/秒也不是不可能的(第二列)。

88行 ,领先RND(随机播放) ,列出了“由InnoDB的随机启动预读的数量。这发生在一个查询扫描表的一大部分,但在随机顺序。 ”

在87行,不管怎么样,值应该小的多。"87行列表中是不能合理的从InnoDB缓存中读取满足的数据,只好做一个单页的阅读。"换句换说,有多少缓存页面是从硬盘读取的。

在88行,在RND(随机)行,列出了“由InnoDB的随机启动预读的数量。这发生在一个查询扫描表的一大部分,但在随机顺序。”

89行 ,未来的Sql (顺序) ,列出了“由InnoDB的启动顺序预读的数量。发生这种情况时, InnoDB的一个顺序全表扫描。 ”与往常一样,全表扫描通常是一件坏事,并应尽量减少。


Writes: Line 90


像在86行,InnoDB缓冲池写入可以被认为是InnoDB的缓冲池吞吐量的度量。该行列出写入到缓冲池的数量和速度。这个值可能会很高,如果服务器做了很多更新或插入的。


Flushes: Line 91


此行是单纯的缓冲池页面刷新请求数。


Wait Free: Line 92


关于这个变量是从mysql手册引用:

通常情况下,写入的InnoDB缓冲池在后台进行。然而,如果有必要读或创建页并没有干净的页是可用的,它也有必要等待页面首先被刷新。该计数器计数这些等待的实例。如果缓冲池大小设置正确,这个值要小。


InnoDB Lock Report: Lines 94 - 100


InnoDB的行锁状态值被添加在MySQL5.0.3。 MyISAM表是一个表级锁的存储引擎,但InnoDB是行级锁定存储引擎。因此,这些值是使用InnoDB引擎时需要考虑的重要。


Waits: Line 95


这一行显示“次行锁必须等待数。零是最好的。


Current: Line 96


这一行显示“排数锁目前正在等待。“零是最好的。


Time acquiring: Lines 97 - 100


在98,99行和100毫秒的时间以毫秒显示相应的行锁不得不等待总数(98行),平均等待时间(99),和最大等待时间(100)。所有三个指标,零是最好的


InnoDB Data, Pages, Rows Report: Lines 102 - 121

InnoDB的数据行,页,行报告很一般,并因此行,很可能是唯一有用的InnoDB引擎的吞吐量一般指标。这三个部分,数据页数和行,给人很广泛外表到InnoDB的活动。


Data: Lines 103 - 110


第一部分,数据,列出了相应的InnoDB数据四类:读取,写入FSYNC,待定。第一类,读取,是指数据被读取InnoDB引擎做的总数。这并不意味着读取数据字节的总数。它只是意味着多少次的InnoDB已经读取数据,它并不表示什么数据种类或多少数据被读取。

第二类,写,就像是说:它是指总的数据写入数由InnoDB,但这并不表明什么样的数据或多少被写入数据。

第三类,fsync,指的是文件系统的总数量的同步。换句话说:我们有多少次从RAM回硬盘保存数据。这个值会低于读取或写入。

等待,最后一类,又分为3条线(行108,109,110):读取,写入,FSYNC。相应地,这些行是指目前一些数据读取次数,写入,以及尚待fsyncs(等待)。零是最好的。


Pages: Lines 112 - 115


在页数部分具有三类:创建,读取,写入。每个类别都描述自己的和着这三个参考页数中的InnoDB缓冲池。这些值表示已创建的缓冲池页面在哪个数量和速度,读取和写入。然而,没有任何值都表示什么样的页面。因此,这些值也只有有用的InnoDB引擎的吞吐量的一般指标。


Rows: Lines 117 - 121


最后一节,行,是因为它是最普遍的。每本节中的四类(删除,插入,读取,更新)是指在InnoDB表的行。因此,这些值往往是非常大的,而他们的计数(第一列)可能表明小,他们的利率(第二列)是另一个指示InnoDB引擎吞吐量。