• 简介
  • mysql_tzinfo_to_sql
  • mysqlslap
  • mysqldump
  • mysqldumpslow
  • mysqlcheck
  • mysqladmin
  • mysqlbinlog
  • innochecksum
  • my_print_defaults
  • 参考

    简介

    MySQL 提供了许多命令行工具,这些工具可以用来管理 MySQL 服务器、进行数据库备份和恢复、对数据库进行访问控制、对数据库进行压测等等。
    首先,简单介绍下各个命令行。
    ——- MySQL安装、初始化
    mysql_install_db
    初始化 MySQL 数据目录程序,主要是新建数据库,初始化用户;5.7 已使用 mysqld 替换;
    mysql_secure_installation
    安装完之后进行一些安全性配置,例如设置root用户、删除test数据库等;
    mysql_safe
    一个shell脚本程序,用来安全启动mysqld程序;
    mysql_tzinfo_to_sql
    将时区信息转换为SQL语句,可以直接加载到MySQL的mysql.time_zone%文件中;
    mysql_upgrade
    用于升级时检查MySQL表;

——- MySQL客户端程序
mysql
MySQL命令行程序,用于链接数据库;
mysqlslap
压测程序,可以用来简单的对数据库进行性能压测;
mysqldump
逻辑备份程序;
mysqlimport
数据导入工具;

——- MySQL管理和实用程序
mysqlbinlog
用于处理二进制日志文件(binlog),可以用于打印数据;
mysqldumpslow
用于处理慢查询日志文件;
mysqladmin
用于管理MySQL服务器;

——- 其它
my_print_defaults
读取配置文件中的配置选项;

mysql_tzinfo_to_sql

该命令用于加载时区表,首先看下 MySQL 中时区的设置。
——- 查看MySQL当前时间以及当前时区
mysql> SELECT curtime(); # 也可以使用now()
mysql> SHOW VARIABLES LIKE “%time_zone%”;
+—————————+————+
| Variable_name | Value |
+—————————+————+
| system_time_zone | CST | # system使用CST时区
| time_zone | SYSTEM | # 使用system时区,也就是上述的参数
+—————————+————+
2 rows in set (0.00 sec)

——- 修改MySQL时区为北京时间,也即东8区;并立即生效
mysql> SET [GLOBAL | SESSION] time_zone=’+8:00’;
mysql> FLUSH PRIVILEGES;

——- 也可以直接修改配置文件,需要重启服务器
$ cat /etc/my.cnf
[mysqld]
default-time_zone = ‘+8:00’
Linux 系统中,与时区相关的内容保存在 /usr/share/zoneinfo 目录下;MySQL 中与时区相关的信息保存在 mysql.time_zone% 表中,可以通过该命令将时区信息导入到 MySQL 中。
——- 将全部时区信息,或者指定时区信息转换为SQL,并导入到MySQL中
$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root mysql
$ mysql_tzinfo_to_sql tz_file tz_name | mysql -u root mysql

——- 如果有闰秒,则同时设置
$ mysql_tzinfo_to_sql —leap tz_file | mysql -u root mysql

mysqlslap

这是一个压测工具,源码在 client/mysqlslap.c,测试的步骤为:A) 创建数据库+表;B) 插入测试数据;C) 执行压测;D) 删除创建的数据库。
常见参数为:
—delimiter
分隔符,用于分割命令行或文件指定的SQL;
—auto-generate-sql, -a
自动生成测试表和数据,并自动生成 SQL 脚本来测试并发压力;
—create-schema (mysqlslap)
测试 schema 名称,也就是 database;
—only-print
只打印测试语句而不实际执行;
—concurrency=N, -c N
控制并发,用于模拟多少个客户端同时执行select,可以指定多个数值,用于不同迭代时的并发;
—iterations=N, -i N
执行的迭代次数,代表要在不同并发环境下,各自运行测试多少次;
—number-of-queries=N
总的测试查询次数,其值 = 并发客户数 x 每次查询数;
—debug-info, -T
最后执行结果打印内存和 CPU 的相关信息;
—auto-generate-sql-load-type=type
测试语句的类型,代表要测试的环境是读操作还是写操作还是两者混合的,取值包括:read,key,write,update和mixed(默认);
—auto-generate-sql-add-auto-increment
代表对生成的表自动添加auto_increment列,从5.1.18版本开始支持;
—number-char-cols=N, -x N
自动生成的测试表中包含多少个字符类型的列,默认1;
—number-int-cols=N, -y N
自动生成的测试表中包含多少个数字类型的列,默认1;
—query=name,-q
使用自定义脚本执行测试,例如可以调用自定义的一个存储过程或者sql语句来执行测试;
—commint=N
多少条DML后提交一次;
—compress, -C
如果服务器和客户端支持都压缩,则压缩信息传递;
—engine=engine_name, -e engine_name
代表要测试的引擎,可以有多个,用分隔符隔开。例如:—engines=myisam,innodb;
—detach=N
执行N条语句后断开重连。
如下是常见的测试用例。
——- 单线程测试,打印执行的SQL,查看具体做了什么
$ mysqlslap —auto-generate-sql —only-print -uroot -pYourPassword

——- 设置并发以及循环次数,也就是说在并发为10,20,50时,均执行4次,返回10,20,50时的统计结果
$ mysqlslap —auto-generate-sql —concurrency=10,20,50 —iterations=4 —number-of-queries 1000 \
-uroot -pYourPassword

——- 测试不同类型存储引擎的性能指标
$ mysqlslap —auto-generate-sql —concurrency=10,20,50 —iterations=4 —number-of-queries 1000 \
—engine=myisam,innodb -uroot -pYourPassword

mysqldump

这是一个逻辑备份工具,其处理流程基本如下。
01 Connect root@localhost on
02 Query /!40100 SET @@SQL_MODE=’’ /
03 Init DB foobar
04 Query SHOW TABLES LIKE ‘foobar’
05 Query LOCK TABLES foobar READ /!32311 LOCAL /
06 Query SET OPTION SQL_QUOTE_SHOW_CREATE=1
07 Query SHOW CREATE TABLE foobar
08 Query SHOW FIELDS FROM foobar
09 Query SHOW TABLE STATUS LIKE ‘foobar’
11 Query SELECT FROM foobar
12 Query UNLOCK TABLES
13 Quit
接下来,主要查看一些常见的参数。
-q
导出数据时加了一个SQL_NO_CACHE来确保不会读取缓存里的数据,第11行修改如下;
Query SELECT /
!40001 SQL_NO_CACHE / FROM foobar

—lock-tables
跟上面类似,不过多加了一个READ LOCAL LOCK,该锁不会阻止读,也不会阻止新的数据插入;

—lock-all-tables
备份前会发起一个全局的读锁,会阻止对所有表的写入,以此确保数据的一致性,备份完成后会话断开,会自动解锁;
会在开头增加如下命令;
Query FLUSH TABLES
Query FLUSH TABLES WITH READ LOCK

—master-data
和—lock-all-tables参数相同,同时多了个SHOW MASTER STATUS命令;
Query FLUSH TABLES
Query FLUSH TABLES WITH READ LOCK
Query SHOW MASTER STATUS

—single-transaction
InnoDB表在备份时,通常会启用参数来保证备份的一致性,其工作原理是设定本次会话的隔离级别为REPEATABLE READ,
以确保本次会话(dump)时,不会看到其他会话已经提交了的数据;同样开始增加如下命令:
Query SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ
Query BEGIN
Query UNLOCK TABLES

mysqldumpslow

该命令用于处理慢查询日志,这是一个 Perl 脚本程序。首先,需要设置好配置文件。
$ cat /etc/my.cnf
[mysqld]
long_query_time=2 # 设置慢查询的超时时间,单位为秒
log-slow-queries=slow-query.log
另外,可以通过 log-queries-not-using-indexes 参数设置没有使用索引的 SQL 。
可以使用该命令查看慢查询日志,常用的命令可以通过如下方式查看。
常用参数:
-h : 查看帮助信息;
-t NUM: 显示头NUM条记录;
-s ARG: 排序参数,有如下的选项,其中前面添加a表示倒序,如ac、at、al、ar;
c: 记录的次数;
t: 查询时的时间戳;
l: 查询使用的时间;
r: 返回记录数目;
-g REG: 根据正则表达式进行匹配,大小写不敏感;

实例:
——- 返回访问次数最多的20个SQL语句
$ mysqldumpslow -s c -t 20 slow-query.log
——- 按照时间返回前10条里面含有左连接的SQL语句
$ mysqldumpslow -s t -t 10 -g “left join” slow-query.log
通过这个工具可以查询出来那些 SQL 语句是性能的瓶颈,如下是上述命令的输出:
Count: 2 Time=2.31s (5s) Lock=0.00s (0s) Rows=1000.0 (2000), root[root]@[localhost]
SELECT * FROM sms_send WHERE service_id<=N GROUP BY content LIMIT N, N;

输出解析:
出现次数(Count) 2;
最大耗时时间(Time) 2.31s;
累计总耗费时间(Time) 5s;
等待锁的时间(Lock) 0.00s;
等待锁的总耗时(Lock) 0s;
发送给客户端的行总数(Rows) 1000;
扫描的行总数(Rows) 2000;
用户以及SQL语句本身,其中的数字会被替换为N。

mysqlcheck

数据库经常可能遇到错误,譬如数据写入磁盘时发生错误、索引没有同步更新、数据库宕机等;从而可能会导致数据库异常。
mysqlcheck 的功能类似 myisamchk,但其工作不同,前者需要在服务器运行的时候执行,而后者需要停服务。
实际上,mysqlcheck 只是提供了一种方便的使用 SQL 语句的方式,会根据不同类型拼接 SQL 语句,真正调用的还是 CHECK TABLE、REPAIR TABLE、ANALYZE TABLE 和 OPTIMIZE TABLE 命令。
可以通过 3 种方式来调用 mysqlcheck 。
——- 检查表
$ mysqlcheck [options] db_name [tables]

——- 检查多个数据库
$ mysqlcheck [options] —-database DB1 [DB2 DB3…]

——- 检查所有的数据库
$ mysqlcheck [options] —all—database

选项:
—database,-B
指定数据库名,可以为多个;
—all—database,-A
检查所有数据库;
源码在 client/check 目录下,处理过程简单介绍如下。
main()
|-get_options() ← 加载配置文件默认配置
| |-load_defaults() ← 通过load_default_groups指定配置文件加载的groups
|
|-mysql_check()
|-disable_binlog() ← 根据参数设置SET SQL_LOG_BIN=0
|-process_all_databases() ← 处理所有数据库
| |-process_one_db()
| |-process_all_tables_in_db()
| |-process_selected_tables()
|
|-process_selected_tables()
| |-handle_request_for_tables() ← 真正的拼接命令处
|
|-process_databases()
其中 handle_request_for_tables() 函数的处理流程如下。
static int handle_request_for_tables(string tables)
{
string operation, options;

switch (what_to_do) {
case DO_CHECK:
operation = “CHECK”;
if (opt_quick) options+= “ QUICK”;
if (opt_fast) options+= “ FAST”;
if (opt_medium_check) options+= “ MEDIUM”; / Default /
if (opt_extended) options+= “ EXTENDED”;
if (opt_check_only_changed) options+= “ CHANGED”;
if (opt_upgrade) options+= “ FOR UPGRADE”;
break;
case DO_REPAIR:
operation= (opt_write_binlog) ? “REPAIR” : “REPAIR NO_WRITE_TO_BINLOG”;
if (opt_quick) options+= “ QUICK”;
if (opt_extended) options+= “ EXTENDED”;
if (opt_frm) options+= “ USE_FRM”;
break;
case DO_ANALYZE:
operation= (opt_write_binlog) ? “ANALYZE” : “ANALYZE NO_WRITE_TO_BINLOG”;
break;
case DO_OPTIMIZE:
operation= (opt_write_binlog) ? “OPTIMIZE” : “OPTIMIZE NO_WRITE_TO_BINLOG”;
break;
case DO_UPGRADE:
return fix_table_storage_name(tables);
}

string query= operation + “ TABLE “ + tables + “ “ + options;

if (mysql_real_query(sock, query.c_str(), (ulong)query.length()))
{
DBError(sock,
“when executing ‘“ + operation + “ TABLE … “ + options + “‘“);
return 1;
}
print_result();
return 0;
}
也即是实际上会生成如下的命令。
CHECK TABLE table_name {QUICK|FAST|MEDIUM|EXTENDED|CHANGED|FOR UPGRADE}
REPAIR NO_WRITE_TO_BINLOG TABLE table_name {QUICK|EXTENDED|USE_FRM}
ANALYZE NO_WRITE_TO_BINLOG TABLE table_name
OPTIMIZE NO_WRITE_TO_BINLOG TABLE table_name
每个表会记录最近的一次检查时间,可以通过如下命令查看。
mysql> SELECT table_name, check_time FROM information_schema.tables
WHERE table_name = ‘tbl-name’ AND table_schema = ‘db-name’;

mysqladmin

该工具最常见的是用来关闭数据库,还可以查看 MySQL 运行状态、进程信息、关闭进程等,如下是常用的子命令;所有命令可以通过 —help 查看帮助文档。
mysqladmin [option] command [command-option] command ……
参数如下:
extended-status
可获得所有MySQL性能指标,即SHOW GLOBAL STATUS的输出
status
获取当前MySQL的几个基本的状态值,包括线程数、查询量、慢查询等
variables
打印出可用变量
ping
查看服务器是否存活
shutdown
关掉服务器
processlist
显示服务其中活跃线程列表
version
得到服务器的版本信息
password ‘new-password’
新口令,将老口令改为新口令

extended-status

默认输出的都是累计值,可以通过 -r/—relative 查看各个指标的差值;然后再配合 -i/—sleep指定刷新的频率。
$ mysqladmin -uroot -pnew-password -h127.1 -P3307 -r -i 1 extended-status |\
grep “Questions|Queries|Innodb_rows|Com_select |Com_insert |Com_update |Com_delete”

$ mysqladmin -uroot -pnew-password -h127.1 -P3307 -r -i 1 extended-status |\
awk -F”|” ‘{\
if($2 ~ /Variable_name/){\
print “ <——————- “ strftime(“%H:%M:%S”) “ ——————->”;\
}\
if($2 ~ /Questions|Queries|Innodb_rows|Com_select |Com_insert |Com_update |Com_delete/)\
print $2 $3;\
}’

$ mysqladmin -uroot -pnew-password -h127.1 -P3307 -r -i 1 extended-status |\
awk ‘BEGIN{ FS=”|”; count=0; } { \
if($2 ~ /Variable_name/ && ((++count)%20 == 1)){ \
print “—————|————-|—- MySQL Command Status —|——- Innodb row operation ——“;\
print “—-Time—-|—-QPS—-|select insert update delete| read inserted updated deleted”;\
} \
else if ($2 ~ /Queries/){queries=$3;}\
else if ($2 ~ /Com_select /){com_select=$3;}\
else if ($2 ~ /Com_insert /){com_insert=$3;}\
else if ($2 ~ /Com_update /){com_update=$3;}\
else if ($2 ~ /Com_delete /){com_delete=$3;}\
else if ($2 ~ /Innodb_rows_read/){innodb_rows_read=$3;}\
else if ($2 ~ /Innodb_rows_deleted/){innodb_rows_deleted=$3;}\
else if ($2 ~ /Innodb_rows_inserted/){innodb_rows_inserted=$3;}\
else if ($2 ~ /Innodb_rows_updated/){innodb_rows_updated=$3;}\
else if ($2 ~ /Uptime / && count >= 2){\
printf(“ %s |%9d”,strftime(“%H:%M:%S”),queries);\
printf(“|%6d %6d %6d %6d”,com_select,com_insert,com_update,com_delete);\
printf(“|%6d %8d %7d %7d\n”,innodb_rows_read,innodb_rows_inserted,innodb_rows_updated,innodb_rows_deleted);\
}}’

mysqlbinlog

二进制日志 (Binary Log) 是由多个事件 (events) 组成,用于描述对于数据库的修改内容,MySQL 服务器以二进制的形式写入,可以通过该工具显示文件中具体事件的内容。
——- 备份时指定多个binlog文件
$ mysqlbinlog —stop-date=”2015-04-20 9:59:59” mysql-bin.[0-9]* | \
mysql -u root -pyour-password

——- 只恢复单个库example
$ mysqlbinlog —stop-date=”2015-04-20 9:59:59” mysql-bin.000001 | \
mysql -u root -pyour-password —one-database example

——- 指定起始时间以及库
$ mysqlbinlog —start-datetime=’2015-08-05 00:00:00’ —stop-datetime=’2015-08-05 10:00:00’ \
—database=db_name mysql-bin.000001

——- 也可以指定binlog的position位置
$ mysqlbinlog —start-postion=107 —stop-position=1000 —database=db_name mysql-bin.000001

——- 从远程服务器读取
$ mysqlbinlog -u username -p password -h127.1 -P3306 —read-from-remote-server \
—start-datetime=’2015-08-05 00:00:00’ —stop-datetime=’2015-08-05 10:00:00’ mysql-bin.000001

ROW格式解析

首先准备下数据。
CREATE DATABASE test;
USE test;
CREATE TABLE foobar (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
name CHAR(20) NOT NULL,
sex ENUM(‘F’,’M’) NOT NULL DEFAULT ‘M’,
address VARCHAR(30) NOT NULL
) Engine=InnoDB;
INSERT INTO foobar(name,sex,address) VALUES(‘Barton’,’M’,’Washington’),(‘Borg’,’M’,’New Mexico’),
(‘Steven’,’M’,’Colorado’);
UPDATE foobar SET address=’Texas’;
可以直接通过 mysqlbinlog 解析。
——- 解析ROW格式binlog文件
$ mysqlbinlog —no-defaults -v -v —base64-output=DECODE-ROWS mysql-bin.000003
… …
### INSERT INTO test.foobar
### SET
### @1=1 / INT meta=0 nullable=0 is_null=0 /
### @2=’Barton’ / STRING(60) meta=65084 nullable=0 is_null=0 /
### @3=2 / ENUM(1 byte) meta=63233 nullable=0 is_null=0 /
### @4=’Washington’ / VARSTRING(90) meta=90 nullable=0 is_null=0 /
… …
### UPDATE test.foobar
### WHERE
### @1=3 / INT meta=0 nullable=0 is_null=0 /
### @2=’Steven’ / STRING(60) meta=65084 nullable=0 is_null=0 /
### @3=2 / ENUM(1 byte) meta=63233 nullable=0 is_null=0 /
### @4=’Colorado’ / VARSTRING(90) meta=90 nullable=0 is_null=0 /
### SET
### @1=3 / INT meta=0 nullable=0 is_null=0 /
### @2=’Steven’ / STRING(60) meta=65084 nullable=0 is_null=0 /
### @3=2 / ENUM(1 byte) meta=63233 nullable=0 is_null=0 /
### @4=’Texas’ / VARSTRING(90) meta=90 nullable=0 is_null=0 /
@1、@2、@3、@4 分别代表了第 1~4 列。

innochecksum

使用该工具时必须停止 MySQL 服务器,否则会报 “Unable to lock file” 错误,如果是在线的最好使用 CHECK TABLE 命令。
简单来说,该工具会读取 InnoDB 的表空间,计算每个页的 Checksum 值,然后与页中的值比较,如果不同则会报错。
innochecksum —verbose=FALSE —log=/tmp/innocheck.log
常用参数:
—help/info
查看帮助信息;
—verbose
打印详细信息,可以通过—verbose=FALSE关闭;
—count/-c
只打印页的数量信息;
—start-page=NUM/-s NUM; —end-page=NUM/-e NUM; —page=NUM/-p NUM
指定开始、结束页,或者只查看指定的页;
—strict-check/-C
指定checksum算法,通常有innodb、crc32、none,默认是从三者中选择,否则强制指定;
—page-type-summary/-S
打印文件中页的统计信息,包括了总页类型以及数量;
—page-type-dump=file-name/-D file-name
打印各个页的详细信息,将其输出到一个文件中;

常用示例:
——- 检查系统表空间,也可以使用table-name.ibd,默认出错时才会输出异常
innodbchecksum ibdata1
——- 保存文件中各个页的信息,并在最后打印统计信息
innodbchecksum -S -D /tmp/page.info schema/*.ibd
详细使用文档可以参考 innochecksum

my_print_defaults

会按照顺序读取配置文件,并提取相应属组的配置项,可以指定多个属组。
——- 使用示例
$ my_print_defaults mysqlcheck client
—user=myusername
—password=secret
—host=localhost

常见参数如下:
—config-file=file_name, —defaults-file=file_name, -c file_name
只读取如上选项指定的配置文件。
—defaults-extra-file=file_name, —extra-file=file_name, -e file_name
读取全局配置项且在读取用户配置前的配置文件。
如果不添加任何参数,可以看到配置文件默认的加载顺序。
Default options are read from the following files in the given order:
/etc/mysql/my.cnf /etc/my.cnf ~/.my.cnf

参考

关于 MySQL 自带的程序,可以直接参考官方网站 Reference Manual - MySQL Programs