一、案例环境描述
1、环境准备
2CPU,4GB内存
预先安装docker sysstat工具
apt install docker.io sysstat nake git
案例总共由三个容器组成:
1、包括一个 MySQL 数据库应用、
2、一个商品搜索应用
3、一个数据处理的应用。
其中,商品搜索应用以 HTTP 的形式提供了一个接口:
/:返回 Index Page;
/db/insert/products/:插入指定数量的商品信息
/products/:查询指定商品的信息,并返回处理时间。
2、架构图
今天的案例需要两台虚拟机,其中一台作为案例分析的目标机器,运行 Flask 应用,它的 IP 地址是 192.168.0.10;另一台则是作为客户端,请求单词的热度。我画了一张图表示它们的关系。
3、测试环境准备
首先、我们在第一个终端中执行下面命令,拉去本次案例所需的脚本:
git clone https://github.com/feiskyer/linux-perf-examples $ cd linux-perf-examples/mysql-slow
接着,执行下面的命令,运行本次的目录应用,正常情况下,你应该可以看到下面的输出
[root@luoahong mysql-slow]# make run docker run --name=mysql -itd -p 10000:80 -m 800m feisky/mysql:5.6 eb934a265f31aaedc262c89c9dcd201c4b77f704b65119dc683b63726f578a3e docker run --name=dataservice -itd --privileged feisky/mysql-dataservice d7183422cf1213ccc1797a1f5a79fc8f14a997ef3942cf999dab8c2c72dc8b2b docker run --name=app --network=container:mysql -itd feisky/mysql-slow f08ca0395fccbd187a57eba932cd072c8460b1a9decff0e1cde46472c8eb409d
注意容器下面的碎字符串是容器ID,每次运行均会不同,并且你不需要关注它,因为我们只会用到名字
然后,再次运行docker ps命令,确认三个容器都处在运行(Up)状态;
[root@luoahong mysql-slow]# docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f08ca0395fcc feisky/mysql-slow "python /app.py" 27 seconds ago Up 26 seconds app d7183422cf12 feisky/mysql-dataservice "python /dataservice…" 28 seconds ago Up 26 seconds dataservice eb934a265f31 feisky/mysql:5.6 "docker-entrypoint.s…" 29 seconds ago Up 27 seconds 3306/tcp, 0.0.0.0:10000->80/tcp mysql [root@luoahong mysql-slow]#
MySQL数据库的启动过程,需要做一些初始化工作,这通常需要花费几分钟时间,你可以运行dockers log命令、查看它的启动过程
[root@luoahong mysql-slow]# docker logs -f mysql Initializing database 2019-05-30 06:27:03 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details). 2019-05-30 06:27:03 0 [Note] Ignoring --secure-file-priv value as server is running with --bootstrap. 2019-05-30 06:27:25 1 [Note] Server socket created on IP: '::'. ...... 2019-05-30 06:27:25 1 [Warning] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. 2019-05-30 06:27:25 1 [Warning] 'proxies_priv' entry '@ root@eb934a265f31' ignored in --skip-name-resolve mode. 2019-05-30 06:27:25 1 [Note] Event Scheduler: Loaded 0 events 2019-05-30 06:27:25 1 [Note] mysqld: ready for connections. Version: '5.6.42-log' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server (GPL)
确认商品搜索应用在10000端口监听,确认它也已经正常运行
[root@luoahong tools]# curl http://127.0.0.1:10000/ Index Page[root@luoahong tools]#
二、故障现象
1、发现故障
运行make init命令,初始化数据库、插入10000条商品信息(这个过程比较慢,大约需要十几分钟的时
[root@luoahong mysql-slow]# make init docker exec -i mysql mysql -uroot -P3306 < tables.sql curl http://127.0.0.1:10000/db/insert/products/20000 insert 20000 lines
在第二个终端,访问一下商品搜索的接口、看看能不能找到想要的商品、执行如下的curl命令
[root@luoahong mysql-slow]# curl http://192.168.118.115:10000/products/geektime Got data: () in 8.804400205612183 sec
2、故障现象
稍等一会儿,你会发现,这个接口返回的是空数据,而且处理时间超过15秒,这么慢的响应速度让人无法忍受,到底出了什么问题呢?
三、分析过程
在第二个终端继续执行下面的命令
[root@luoahong ~]# while true; do curl http://192.168.118.115:10000/products/geektime; sleep 5; done Got data: () in 8.62768268585205 sec Got data: () in 9.515994548797607 sec Got data: () in 8.497008562088013 sec Got data: () in 8.946581602096558 sec Got data: () in 8.66761040687561 sec Got data: () in 9.343888998031616 sec Got data: () in 8.72763991355896 sec Got data: () in 8.446544647216797 sec Got data: () in 8.668050289154053 sec Got data: () in 9.259597539901733 sec Got data: () in 8.74580430984497 sec Got data: () in 8.766760110855103 sec Got data: () in 8.431026220321655 sec
1、首先、我们在中断执行top命令、分析系统的CPU使用情况:
观察top的输出,我们发现:
1、两个CPU的iowat都比较高、特别是cpu0,iowat已经超过了60%
2、而具体到各个进程, CPU 使用率并不高,最高的也只有17.2
2、既然CPU嫌疑不大,那问题应该在I/O上,停止top命令;然后执行iostat命令,看看有没有I/O性能问题
[root@luoahong mysql-slow]# iostat -d -x 1 Linux 5.1.0-1.el7.elrepo.x86_64 (luoahong) 05/30/2019 _x86_64_ (2 CPU) Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 16.27 10181.73 0.02 0.10 39.60 625.71 18.35 976.48 0.46 2.44 3.22 53.23 0.00 0.00 0 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 30.00 4436.00 0.00 0.00 7.23 147.87 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.20 3.50 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 129.00 110716.00 1.00 0.77 46.16 858.26 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 5.89 19.10 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 118.00 112244.00 1.00 0.84 50.22 951.22 1.00 4.00 0.00 0.00 34.00 4.00 0.00 0.00 0.00 0.00 0.00 0.00 5.90 18.70 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 116.00 118784.00 0.00 0.00 54.59 1024.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 6.27 18.50 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 119.00 121600.00 0.00 0.00 53.70 1021.85 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 6.34 19.20 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 126.00 118788.00 2.00 1.56 54.24 942.76 1.00 4.00 0.00 0.00 40.00 4.00 0.00 0.00 0.00 0.00 0.00 0.00 6.81 19.20 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 106.00 109056.00 0.00 0.00 62.00 1028.83 1.00 7.50 0.00 0.00 52.00 7.50 0.00 0.00 0.00 0.00 0.00 0.00 6.50 16.50 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 101.00 102656.00 0.00 0.00 63.90 1016.40 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 6.47 16.10 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 127.72 120146.53 1.98 1.53 53.74 940.68 1.98 11.88 0.00 0.00 42.50 6.00 0.00 0.00 0.00 0.00 0.00 0.00 6.89 19.50 Device r/s rkB/s rrqm/s %rrqm r_await rareq-sz w/s wkB/s wrqm/s %wrqm w_await wareq-sz d/s dkB/s drqm/s %drqm d_await dareq-sz aqu-sz %util sda 102.00 93000.00 0.00 0.00 48.75 911.76 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 4.92 14.50
1、磁盘 sda 每秒的读数据为 32 MB
2、而 I/O 使用率高达 97%
3、接近饱和,这说明,磁盘 sda 的读取确实碰到了性能瓶颈
3、如何知道这些进程是那些进程导致的呢?
[root@luoahong mysql-slow]# pidstat -d 1 Linux 5.1.0-1.el7.elrepo.x86_64 (luoahong) 05/30/2019 _x86_64_ (2 CPU) 04:18:28 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command 04:18:29 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command 04:18:30 PM 0 10641 4.00 4.00 0.00 0 python 04:18:30 PM 0 10945 0.00 0.00 0.00 1 kworker/0:0-events 04:18:30 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command 04:18:31 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command 04:18:32 PM 0 10945 0.00 0.00 0.00 1 kworker/0:0-events_power_efficient 04:18:32 PM UID PID kB_rd/s kB_wr/s kB_ccwr/s iodelay Command 04:18:33 PM 0 10263 556.00 0.00 0.00 0 bash 04:18:33 PM 999 10560 15872.00 0.00 0.00 0 mysqld 04:18:33 PM 0 10641 0.00 4.00 0.00 0 python 04:18:33 PM 0 11084 5792.00 0.00 0.00 29 curl
4、分析进程的数据读取 需要用到strace+ lsof 组合。
为什么mysqld会读取大量的磁盘数据呢?按照前面猜测,我们提到过、这有可能是慢查询问题
可是、回想一下、慢查询的现象大多是cpu使用率高,但这里的看到的确实I/O问题,看来、这并不是一个单纯的
慢查询问题,我们有必要分析一下mysql读取的数据
我们知道,MySQL 是一个多线程的数据库应用,为了不漏掉这些线程的数据读取情况,你要记得在执行stace 命令时,加上 -f 参数:
strace -f -p 10560 [pid 10919] read(37, "gOvH0QGqpShDOt3TFpB7mWFxIsGFpxEQ"..., 131072) = 131072 [pid 10919] read(37, "veWjWoElqB6E26n7ghhjHtFdRfUcQ4Vt"..., 20480) = 20480 [pid 10919] read(37, "tiyHTvaaW6XOT9Sq7dZMmNimVOPvFoWp"..., 131072) = 131072 [pid 10919] read(37, "78fMhVd5SH38edDFgwuLpDNdiNIp7mHo"..., 24576) = 24576 [pid 10919] read(37, "GpjARraEFkUJCzaO41iaoiVmWW730hS1"..., 131072) = 131072 [pid 10919] read(37, "T4K9rAkBz3cApPxKNJyPpSU6lK4CuUaq"..., 20480) = 20480 [pid 10919] read(37, "dUndUh2lEwhYK6ueXqfZ6jjj1Y9OSniP"..., 131072) = 131072 [pid 10919] read(37, "r7WsV96IojCmciSHlgk0Pp7oqkoq7hL4"..., 24576) = 24576 [pid 10919] read(37, "4kvN7g1EidOep0AFEN0bzOLNYjFt3FM0"..., 131072) = 131072
线程 10919 正在读取大量数据、且读取文件的描述符编号为 37。
5、这儿的 37 又对应着哪个文件呢?
[root@luoahong ~]# lsof -p 10919 [root@luoahong ~]# echo $? 1
为什么 lsof 命令执行失败了呢?
遇到现象解释不了,先去查查工具文档。事实上,通过查询 lsof 的文档,你会发现,-p 参数需要指定进程号,而我们刚才传入的是线程号,所以 lsof 失败了
[root@luoahong ~]# pstree -a -p 10560 mysqld,10560 --log_bin=on --sync_binlog=1 ├─{mysqld},10856 ├─{mysqld},10857 ├─{mysqld},10858 ├─{mysqld},10859 ├─{mysqld},10860 ├─{mysqld},10861 ├─{mysqld},10862 ├─{mysqld},10863 ├─{mysqld},10864 ├─{mysqld},10865 ├─{mysqld},10867 ├─{mysqld},10868 ├─{mysqld},10869 ├─{mysqld},10870 ├─{mysqld},10871 ├─{mysqld},10872 ├─{mysqld},10873 ├─{mysqld},10874 ├─{mysqld},10875 ├─{mysqld},10876 └─{mysqld},10919
你会发现,mysqld 其实还有很多正在运行的其他线程:
6、找到了原因,lsof 的问题就容易解决了。把线程号换成进程号、继续执行 lsof 命令:
[root@luoahong ~]# lsof -p 10560 COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME mysqld 10560 polkitd cwd DIR 8,2 239 455186 /var/lib/mysql mysqld 10560 polkitd rtd DIR 0,42 28 1315612 / mysqld 10560 polkitd txt REG 0,42 15759280 39165788 /usr/sbin/mysqld ...... mysqld 10560 polkitd DEL REG 0,17 65017 /[aio] mysqld 10560 polkitd DEL REG 0,17 65016 /[aio] mysqld 10560 polkitd DEL REG 0,17 65015 /[aio] mysqld 10560 polkitd DEL REG 0,17 65014 /[aio] mysqld 10560 polkitd DEL REG 0,17 65013 /[aio] mysqld 10560 polkitd DEL REG 0,17 65012 /[aio] mysqld 10560 polkitd DEL REG 0,17 65011 /[aio] mysqld 10560 polkitd DEL REG 0,17 65010 /[aio] mysqld 10560 polkitd DEL REG 0,17 65009 /[aio] mysqld 10560 polkitd DEL REG 0,17 65008 /[aio] mysqld 10560 polkitd DEL REG 0,17 65007 /[aio] mysqld 10560 polkitd DEL REG 0,17 65004 /[aio] mysqld 10560 polkitd 0u CHR 136,0 0t0 3 /dev/pts/0 mysqld 10560 polkitd 1u CHR 136,0 0t0 3 /dev/pts/0 mysqld 10560 polkitd 2u CHR 136,0 0t0 3 /dev/pts/0 mysqld 10560 polkitd 3u REG 8,2 48 21165914 /var/lib/mysql/on.index mysqld 10560 polkitd 4uW REG 8,2 12582912 18611645 /var/lib/mysql/ibdata1 mysqld 10560 polkitd 5u REG 0,42 0 74328016 /tmp/ibbSKXmR (deleted) mysqld 10560 polkitd 6u REG 0,42 0 74328017 /tmp/ibeUxi1R (deleted) mysqld 10560 polkitd 7u REG 0,42 0 74328018 /tmp/ibaQWDFS (deleted) mysqld 10560 polkitd 8u REG 0,42 0 74328019 /tmp/iboRiwZT (deleted) mysqld 10560 polkitd 9uW REG 8,2 50331648 18611646 /var/lib/mysql/ib_logfile0 mysqld 10560 polkitd 10uW REG 8,2 50331648 18611647 /var/lib/mysql/ib_logfile1 mysqld 10560 polkitd 11w REG 8,2 820 21165905 /var/lib/mysql/fef6fa81243e-slow.log mysqld 10560 polkitd 12u REG 0,42 0 74328020 /tmp/ibellVRU (deleted) mysqld 10560 polkitd 13u sock 0,9 0t0 65025 protocol: TCPv6 mysqld 10560 polkitd 14w REG 8,2 1026029812 21165913 /var/lib/mysql/on.000004 mysqld 10560 polkitd 15u sock 0,9 0t0 65026 protocol: UNIX mysqld 10560 polkitd 16u REG 8,2 2048 74317349 /var/lib/mysql/mysql/user.MYI mysqld 10560 polkitd 17u REG 8,2 452 74317350 /var/lib/mysql/mysql/user.MYD mysqld 10560 polkitd 18u REG 8,2 5120 74317346 /var/lib/mysql/mysql/db.MYI mysqld 10560 polkitd 19u REG 8,2 880 74317347 /var/lib/mysql/mysql/db.MYD mysqld 10560 polkitd 20u REG 8,2 5120 74317493 /var/lib/mysql/mysql/proxies_priv.MYI mysqld 10560 polkitd 21u REG 8,2 1386 74317494 /var/lib/mysql/mysql/proxies_priv.MYD mysqld 10560 polkitd 22u REG 8,2 4096 74317361 /var/lib/mysql/mysql/tables_priv.MYI mysqld 10560 polkitd 23u REG 8,2 0 74317362 /var/lib/mysql/mysql/tables_priv.MYD mysqld 10560 polkitd 24u REG 8,2 4096 74317364 /var/lib/mysql/mysql/columns_priv.MYI mysqld 10560 polkitd 25u REG 8,2 0 74317365 /var/lib/mysql/mysql/columns_priv.MYD mysqld 10560 polkitd 26u REG 8,2 4096 74317468 /var/lib/mysql/mysql/procs_priv.MYI mysqld 10560 polkitd 27u REG 8,2 0 74317469 /var/lib/mysql/mysql/procs_priv.MYD mysqld 10560 polkitd 28u REG 8,2 1024 74317358 /var/lib/mysql/mysql/servers.MYI mysqld 10560 polkitd 29u REG 8,2 0 74317359 /var/lib/mysql/mysql/servers.MYD mysqld 10560 polkitd 30uW REG 8,2 98304 74317489 /var/lib/mysql/mysql/slave_master_info.ibd mysqld 10560 polkitd 31uW REG 8,2 98304 74317491 /var/lib/mysql/mysql/slave_worker_info.ibd mysqld 10560 polkitd 32uW REG 8,2 98304 74317487 /var/lib/mysql/mysql/slave_relay_log_info.ibd mysqld 10560 polkitd 33u REG 8,2 2048 74317477 /var/lib/mysql/mysql/event.MYI mysqld 10560 polkitd 34u REG 8,2 0 74317478 /var/lib/mysql/mysql/event.MYD mysqld 10560 polkitd 36u REG 8,2 207872 74328024 /var/lib/mysql/test/products.MYI mysqld 10560 polkitd 37u REG 8,2 1024880000 74328025 /var/lib/mysql/test/products.MYD
mysqld 进程确实打开了大量文件
而根据文件描述符(FD)的编号,我们知道,描述符为 37 的是一个路径为/var/lib/mysql/test/products.MYD的文件,这里注意37后面的U表示,mysqld读写的方式访问文件
看到这个文件,熟悉 MySQL 的你可能笑了:
1、MYD 文件,是 MyISAM 引擎用来存储表数据的文件;
2、文件名就是数据表的名字;
3、而这个文件的父目录,也就是数据库的名字。
换句话说,这个文件告诉我们,mysqld 在读取数据库 test中的products表
7、查看 mysqld 在管理数据库 test 时的存储文件
[root@luoahong ~]# docker exec -it mysql ls /var/lib/mysql/test/ db.opt products.MYD products.MYI products.frm
从这里你可以发现,/var/lib/mysql/test/ 目录中有四个文件,每个文件的作用分别是:
1、MYD 文件用来存储表的数据;
2、MYI 文件用来存储表的索引;
3、frm 文件用来存储表的元信息(比如表结构);
4、opt 文件则用来存储数据库的元信息(比如字符集、字符校验规等
8、这些文件到底是不是 mysqld 正在使用的数据库文件呢?
[root@luoahong mysql-slow]# docker exec -i -t mysql mysql -e 'show global variables like "%datadir%";' +---------------+-----------------+ | Variable_name | Value | +---------------+-----------------+ | datadir | /var/lib/mysql/ | +---------------+-----------------+
9、数据库中正在执行什么样的 SQL 了
不过,为了保证 SQL 语句不截断、这里我们可以执行 show full processlist命令。如果一切正常,你应该可以看到如下输出:
mysql> show full processlist; +-----+------+-----------------+------+---------+------+--------------+-----------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +-----+------+-----------------+------+---------+------+--------------+-----------------------------------------------------+ | 183 | root | localhost | NULL | Query | 0 | init | show full processlist | | 188 | root | 127.0.0.1:60018 | test | Query | 1 | Sending data | select * from products where productName='geektime' | +-----+------+-----------------+------+---------+------+--------------+-----------------------------------------------------+ 2 rows in set (0.00 sec)
10、explain 命令确认是否建立索引
根据这些信息,我们可以确定,这条查询语句压根儿没有使用索引,所以查询时,会扫描全表,并且扫描行数高达 20000 行。响应速度那么慢也就难怪了。
mysql> use test; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed mysql> explain select * from products where productName='geektime'; +----+-------------+----------+------+---------------+------+---------+------+-------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+----------+------+---------------+------+---------+------+-------+-------------+ | 1 | SIMPLE | products | ALL | NULL | NULL | NULL | NULL | 20000 | Using where | +----+-------------+----------+------+---------------+------+---------+------+-------+-------------+ 1 row in set (0.01 sec)
查询 products 表的结构
mysql> show create table products; +----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | Table | Create Table | +----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ | products | CREATE TABLE `products` ( `id` int(11) NOT NULL, `productCode` text NOT NULL COMMENT '产品代码', `productName` text NOT NULL COMMENT '产品名称', `productLine` text NOT NULL COMMENT '产品线', `productScale` text NOT NULL, `productVendor` text NOT NULL, `productDescription` text NOT NULL, `quantityInStock` smallint(6) NOT NULL COMMENT '库存', `buyPrice` decimal(10,2) NOT NULL COMMENT '价格', `MSRP` decimal(10,2) NOT NULL COMMENT '建议零售价', PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC | +----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+ 1 row in set (0.01 sec)
你会看到,它只有一个 id 主键,并不包括 productName 的索引:
11、创建索引
mysql> CREATE INDEX products_index ON products (productName); ERROR 1170 (42000): BLOB/TEXT column 'productName' used in key specification without a key length
你会看到,它只有一个 id 主键,并不包括 productName 的索引:就必须为 productName 指定一个前缀长度
mysql> CREATE INDEX products_index ON products (productName(64)); Query OK, 20000 rows affected (38.83 sec) Records: 20000 Duplicates: 0 Warnings: 0
现在可以看到,索引已经建好了。能做的都做完了,最后就该检查一下,性能问题是否已经解决了。
查看还在执行的 curl 命令的结果:
[root@luoahong ~]# while true; do curl http://192.168.118.115:10000/products/geektime; sleep 5; done Got data: () in 8.62768268585205 sec Got data: () in 8.635614395141602 sec Got data: () in 8.58862042427063 sec Got data: () in 22.183180809020996 sec Got data: () in 0.19141674041748047 sec Got data: () in 0.010161638259887695 sec Got data: () in 0.006281137466430664 sec Got data: () in 0.006078481674194336 sec
查看还在执行的 curl 命令的结果:
四、DataService 是一个严重影响 MySQL 性能的干扰应用
1、停止DataService容器
[root@luoahong ~]# [root@luoahong ~]# docker rm -f dataservice dataservice
2、删除索引
$ docker exec -i -t mysql mysql mysql> mysql> mysql> DROP INDEX products_index ON products; Query OK, 20000 rows affected (16.24 sec) Records: 20000 Duplicates: 0 Warnings: 0
3、观察性能
[root@luoahong ~]# vmstat 1 procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 1 0 35340 1429716 0 1131008 0 3 20224 421 409 517 10 5 70 16 0 0 1 35340 1427952 0 1130840 16 0 110096 0 607 429 2 11 55 33 0 0 1 35340 1429188 0 1130904 0 0 111368 0 583 361 1 11 50 38 0 0 1 35852 1429212 0 1131276 0 388 93088 388 680 536 1 11 52 37 0 2 0 36108 1427440 0 1131444 0 240 80744 240 624 390 3 13 50 35 0 1 1 40716 1427952 0 1132732 0 4808 102312 4808 527 376 1 9 51 39 0 0 0 40716 1430220 0 1132712 0 0 35228 0 331 335 1 5 78 16 0 0 0 40716 1430220 0 1132712 0 0 0 0 123 210 0 0 100 0 0 2 0 40716 1430220 0 1132712 0 0 0 0 124 202 1 1 99 0 0 0 0 40716 1430220 0 1132712 0 0 0 0 142 226 0 1 99 0 0 1 0 40716 1430220 0 1132712 0 0 0 0 194 246 1 2 97 0 0
4、观察 curl 的结果:
Got data: () in 13.258588314056396 sec Got data: () in 9.701965808868408 sec Got data: () in 9.14393663406372 sec Got data: () in 9.088764190673828 sec Got data: () in 5.43427038192749 sec Got data: () in 5.0143187046051025 sec Got data: () in 6.960656404495239 sec Got data: () in 7.294579267501831 sec Got data: () in 4.582106590270996 sec Got data: () in 4.365068674087524 sec