MySQL命令行的几个用法(续)
继续上一篇的话题,介绍mysql命令行的一些小技巧。
1.以html格式输出结果
使用mysql客户端的参数–html或者-T,则所有SQL的查询结果会自动生成为html的table代码
$ mysql -uroot --html Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 3286 Server version: 5.1.24-rc-log MySQL Community Server (GPL) Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> select * from test.test; <TABLE BORDER=1><TR><TH>i</TH></TR><TR><TD>1</TD></TR><TR><TD>2</TD></TR></TABLE> 2 rows in set (0.00 sec)
2.以xml格式输出结果
跟上面差不多,使用–xml或者-X选项,可以将结果输出为xml格式
$ mysql -uroot --xml
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 3287
Server version: 5.1.24-rc-log MySQL Community Server (GPL)
Type 'help;' or '\h' for help. Type '\c' to clear the buffer.
mysql> select * from test.test;
<?xml version="1.0"?>
<resultset statement="select * from test.test;"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<row>
<field name="i">1</field>
</row>
<row>
<field name="i">2</field>
</row>
</resultset>
2 rows in set (0.00 sec)
3.修改命令提示符
使用mysql的–prompt=选项,或者进入mysql命令行环境后使用prompt命令,都可以修改提示符
mysql> prompt \u@\d> PROMPT set to '\u@\d>' root@(none)>use mysql 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 root@mysql>
其中\u表示当前连接的用户,\d表示当前连接的数据库,其他更多的可选项可以参考man mysql
MySQL如何获取当前执行的SQL
在MySQL的客户端中通过show [full] processlist可以看到当前所有线程,以及线程的状态,当然也包括执行中的sql,但是显示的语句不完全,并且有很多空闲线程会造成干扰。
这里要介绍一个非常好用的开源工具innotop(sourceforge已经被墙了,要过去先找梯子),由于是用perl写的,所以需要安装相关的perl模块,包括DBI,DBD::mysql,Term::ReadKey和Time::HiRes,这些模块都可以到CPAN找到。
用innotop的Q模式则可以完美的解决获取当前运行的SQL的问题。innotop -m Q 或者innotop进入后再按shift+q进入Query list模式:
Query List (? for help) mysql01, 75+03:16:16, 774.20 QPS, 83 thd, 5.1.24-rc-log CXN When Load QPS Slow QCacheHit KCacheHit BpsIn BpsOut my120 Now 0.00 774.20 0 40.22% 100.00% 207.98k 1.46M my120 Total 0.00 212.69 2 29.70% 100.00% 56.90k 402.15k CXN Cmd ID User Host DB Time Query mysql01 Query 20936 poster 192.168.1.1 poster 00:00 select a.poster_id, a.pic_id, a.gmt_create, a.gmt_modified, a.url, a.no
然后按e并输入thread ID显示执行计划或者按f显示完整sql语句,或者按o显示系统优化过的语句(需要MySQL的版本支持EXPLAIN EXTENDED)。个人感觉,还是e最有用,其他两个选项,则有点鸡肋了。
Query List (? for help) mysql01, 75+03:16:16, 774.20 QPS, 83 thd, 5.1.24-rc-log
EXPLAIN PARTITIONS
select a.poster_id, a.pic_id, a.gmt_create, a.gmt_modified, a.url, a.notes,
a.type, a.indexed, a.user_id, a.user_nick, b.pic_path
from poster.poster_pic a inner join poster.picture b on
(a.pic_id = b.id) where a.poster_id = 3390 order by a.indexed
______________ Sub-Part 1 ______________ ________ Sub-Part 1 ________
Select Type: SIMPLE Select Type: SIMPLE
Table: a Table: b
Partitions: Partitions:
Type: ref Type: eq_ref
Poss. Keys: PRIMARY Poss. Keys: PRIMARY
Index: PRIMARY Index: PRIMARY
Key Length: 4 Key Length: 8
Index Ref: const Index Ref: poster.a.PIC_ID
Row Count: 14 Row Count: 1
Special: Using where; Using filesort Special:
Press e to explain, f for full query, o for optimized query
Query List (? for help) mysql01, 75+03:16:16, 774.20 QPS, 83 thd, 5.1.24-rc-log select a.poster_id, a.pic_id, a.gmt_create, a.gmt_modified, a.url, a.notes, a.type, a.indexed, a.user_id, a.user_nick, b.pic_path from poster.poster_pic a inner join poster.picture b on (a.pic_id = b.id) where a.poster_id = 3390 order by a.indexed Press e to explain, f for full query, o for optimized query
Query List (? for help) mysql01, 75+03:16:16, 774.20 QPS, 83 thd, 5.1.24-rc-log select a.poster_id, a.pic_id, a.gmt_create, a.gmt_modified, a.url, a.notes, a.type, a.indexed, a.user_id, a.user_nick, b.pic_path from poster.poster_pic a inner join poster.picture b on (a.pic_id = b.id) where a.poster_id = 3390 order by a.indexed Note: select `poster`.`a`.`POSTER_ID` AS `poster_id`,`poster`.`a`.`PIC_ID` AS `pic_id`,`poster`.`a`.`GMT_CREATE` AS `gmt_create`, `poster`.`a`.`GMT_MODIFIED` AS `gmt_modified`, `poster`.`a`.`URL` AS `url`,`poster`.`a`.`NOTES` AS `notes`, `poster`.`a`.`TYPE` AS `type`,`poster`.`a`.`INDEXED` AS `indexed`, `poster`.`a`.`USER_ID` AS `user_id`,`poster`.`a`.`user_nick` AS `user_nick`,`poster`.`b`.`PIC_PATH` AS `pic_path` from `poster`.`poster_pic` `a` join `poster`.`picture` `b` where ((`poster`.`b`.`ID` = `poster`.`a`.`PIC_ID`) and (`poster`.`a`.`POSTER_ID` = 3390)) order by `poster`.`a`.`INDEXED` Press e to explain, f for full query, o for optimized query
那么innotop是从哪里取的数据呢?应该是通过information_schema.processlist来获得完整的sql语句,并且根据COMMAND来过滤掉空闲线程的。
mysql> desc information_schema.processlist; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | ID | bigint(4) | NO | | 0 | | | USER | varchar(16) | NO | | | | | HOST | varchar(64) | NO | | | | | DB | varchar(64) | YES | | NULL | | | COMMAND | varchar(16) | NO | | | | | TIME | bigint(7) | NO | | 0 | | | STATE | varchar(64) | YES | | NULL | | | INFO | longtext | YES | | NULL | | +---------+-------------+------+-----+---------+-------+ 8 rows in set (0.00 sec)
MySQL命令行的几个用法
MySQL的客户端命令行工具,有很多方便使用者的特性,某些方面甚至可以说比Oracle的sqlplus更加人性化。当然从整体来说,还是sqlplus更加方便些,这么说或许是我对sqlplus更加熟悉吧。这里记录下MySQL命令行几个比较常用的特性。
1.使用\G按行垂直显示结果
如果一行很长,需要这行显示的话,看起结果来就非常的难受。在SQL语句或者命令后使用\G而不是分号结尾,可以将每一行的值垂直输出。这个可能也是大家对于MySQL最熟悉的区别于其他数据库工具的一个特性了。
*************************** 1. row ***************************
id: 1
check_day: 2008-06-26
db_name: TBDB1
arc_size: 137
arc_num: 166
per_second: 1.6
avg_time: 8.7
2.使用pager设置显示方式
如果select出来的结果集超过几个屏幕,那么前面的结果一晃而过无法看到。使用pager可以设置调用os的more或者less等显示查询结果,和在os中使用more或者less查看大文件的效果一样。
使用more
PAGER set to 'more'
mysql> \P more
PAGER set to 'more'
使用less
PAGER set to 'less'
mysql> \P less
PAGER set to 'less'
还原成stdout
PAGER set to stdout
3.使用tee保存运行结果到文件
这个类似于sqlplus的spool功能,可以将命令行中的结果保存到外部文件中。如果指定已经存在的文件,则结果会附加到文件中。
Logging to file 'output.txt'
或者
mysql> \T output.txt
Logging to file 'output.txt'
mysql> notee
Outfile disabled.
或者
mysql> \t
Outfile disabled.
4.执行OS命令
Linux
mysql> \! uname
Linux
5.执行SQL文件
+----------------+
| current_date() |
+----------------+
| 2008-06-28 |
+----------------+
1 row in set (0.00 sec)
或者
mysql> \. test.sql
+----------------+
| current_date() |
+----------------+
| 2008-06-28 |
+----------------+
1 row in set (0.00 sec)
其他还有一些功能,可以通过help或者?获得MySQL命令行支持的一些命令。
用HSCALE实现MySQL的数据分布式存储
针对单个表过大造成的性能问题,MySQL在5.1开始引入了分区表(partition),可以将数据在内部拆分存储,对应用透明,但是分区表只能将表在同一个数据库内部分解,而且对于表的维护(比如执行alter table)还是比较麻烦。手工分表也是一个解决方法,手工分表还有一个好处是可以将表分布到不同的服务器中,实现分布式存储。但是手工分表要求应用程序做相应的改写,以支持从不同的表中来存取数据。
HSCALE简单来说就是一个支持手工分表的中间层,对于应用来说看起来还是一个表,而由HSCALE来负责底层子表的数据存取。HSCALE是基于MySQL Proxy的一个插件应用,通过MySQL Proxy的lua脚本拦截分拆对应的SQL语句来实现数据的分布存储,而且使用lua脚本可以自由定制分表策略,比起MySQL自己的partition更加灵活些。现在版本还是0.2,功能有限,只能实现同库分表,但是基于MySQL Proxy的架构,未来要实现示分库分表也不是什么难事。
作者利用mysqlslap对HSCALE和MySQL Proxy做了几组性能测试,结果参考这里,还有这里。
当然,现在MySQL Proxy和HSCALE都是刚刚起步,要在产品库中应用还有很长的一段路要走,从上面的性能测试中可以看到基于最新的MySQL Proxy 0.7版的HSCALE性能有了较大的提升,期待后续版本有更好的表现。