本节提供有关如何更有效地使用 mysql 的技巧以及有关 mysql 操作行为的信息。
输入行编辑
mysql 支持输入行编辑,这使您能够就地修改当前输入行或调用以前的输入行。例如,左箭头 和 右箭头 键在当前输入行中水平移动,而 上箭头 和 下箭头 键在以前输入行的集合中上下移动。退格键 删除光标前的字符,键入新字符将在光标位置输入它们。要输入该行,请按 回车键。
在 Windows 上,编辑键序列与在控制台窗口中支持的命令编辑相同。在 Unix 上,键序列取决于用于构建 mysql 的输入库(例如,libedit
或 readline
库)。
有关 libedit
和 readline
库的文档可在网上找到。要更改给定输入库允许的键序列集,请在库启动文件中定义键绑定。这是您主目录中的一个文件:.editrc
用于 libedit
和 .inputrc
用于 readline
。
例如,在 libedit
中,Control+W 删除光标之前的全部内容,而 Control+U 删除整行。在 readline
中,Control+W 删除光标前的单词,而 Control+U 删除光标之前的全部内容。如果 mysql 是使用 libedit
构建的,则希望为这两个键使用 readline
行为的用户可以将以下几行添加到 .editrc
文件中(如果需要,可以创建该文件)
bind "^W" ed-delete-prev-word
bind "^U" vi-kill-line-prev
要查看当前的键绑定集,请在 .editrc
文件末尾临时添加一行,该行仅包含 bind
。当 mysql 启动时,它将显示绑定。
禁用交互式历史记录
上箭头 键使您能够从当前会话和以前会话中调用输入行。在共享控制台的情况下,这种行为可能不适合。mysql 支持部分或完全禁用交互式历史记录,具体取决于主机平台。
在 Windows 上,历史记录存储在内存中。Alt+F7 删除当前历史记录缓冲区中存储的所有输入行。它还删除了在 F7 显示并使用 F9(按数字)调用的输入行前面的序列号列表。在按下 Alt+F7 后输入的新输入行将重新填充当前历史记录缓冲区。清除缓冲区不会阻止日志记录到 Windows 事件查看器,如果使用 --syslog
选项启动 mysql,则会发生这种情况。关闭控制台窗口也会清除当前历史记录缓冲区。
要在 Unix 上禁用交互式历史记录,首先删除 .mysql_history
文件(如果存在)(否则,将调用以前的条目)。然后使用 --histignore="*"
选项启动 mysql 以忽略所有新的输入行。要重新启用调用(和日志记录)行为,请在不使用该选项的情况下重新启动 mysql。
如果您阻止创建 .mysql_history
文件(请参阅 控制历史记录文件)并使用 --histignore="*"
启动 mysql 客户端,则交互式历史记录调用功能将完全禁用。或者,如果您省略 --histignore
选项,则可以调用当前会话中输入的输入行。
Windows 上的 Unicode 支持
Windows 提供基于 UTF-16LE 的 API 用于从控制台读取和写入控制台;适用于 Windows 的 mysql 客户端能够使用这些 API。Windows 安装程序在 MySQL 菜单中创建一个名为 MySQL command line client - Unicode
的项目。此项目将调用 mysql 客户端,并将属性设置为通过控制台使用 Unicode 与 MySQL 服务器通信。
要手动利用此支持,请在使用兼容 Unicode 字体控制台内运行 mysql,并将默认字符集设置为支持与服务器通信的 Unicode 字符集
打开一个控制台窗口。
转到控制台窗口属性,选择字体选项卡,然后选择 Lucida Console 或其他兼容 Unicode 字体。这是必要的,因为控制台窗口默认情况下使用 DOS 光栅字体,该字体不适用于 Unicode。
使用 mysql.exe 并添加
--default-character-set=utf8mb4
(或utf8mb3
)选项。此选项是必要的,因为utf16le
是不能用作客户端字符集的字符集之一。请参见 不允许的客户端字符集。
有了这些更改,mysql 将使用 Windows API 以 UTF-16LE 与控制台通信,并以 UTF-8 与服务器通信。(之前提到的菜单项设置了如上所述的字体和字符集。)
为了避免每次运行 mysql 时都执行这些步骤,您可以创建一个调用 mysql.exe 的快捷方式。快捷方式应将控制台字体设置为 Lucida Console 或其他兼容的 Unicode 字体,并将 --default-character-set=utf8mb4
(或 utf8mb3
)选项传递给 mysql.exe。
或者,创建一个仅设置控制台字体的快捷方式,并在您的 my.ini
文件的 [mysql]
组中设置字符集。
[mysql]
default-character-set=utf8mb4 # or utf8mb3
垂直显示查询结果
某些查询结果以垂直方式显示比以通常的水平表格格式显示更具可读性。通过以 \G 而不是分号结尾来终止查询,可以将查询以垂直方式显示。例如,包含换行符的较长文本值通常以垂直输出方式更容易阅读。
mysql> SELECT * FROM mails WHERE LENGTH(txt) < 300 LIMIT 300,1\G
*************************** 1. row ***************************
msg_nro: 3068
date: 2000-03-01 23:29:50
time_zone: +0200
mail_from: Jones
reply: [email protected]
mail_to: "John Smith" <[email protected]>
sbj: UTF-8
txt: >>>>> "John" == John Smith writes:
John> Hi. I think this is a good idea. Is anyone familiar
John> with UTF-8 or Unicode? Otherwise, I'll put this on my
John> TODO list and see what happens.
Yes, please do that.
Regards,
Jones
file: inbox-jani-1
hash: 190402944
1 row in set (0.09 sec)
使用安全更新模式(--safe-updates)
对于初学者而言,一个有用的启动选项是 --safe-updates
(或 --i-am-a-dummy
,其效果相同)。安全更新模式对于您可能已发出 UPDATE
或 DELETE
语句但忘记了指示要修改哪些行的 WHERE
子句的情况很有帮助。通常情况下,此类语句会更新或删除表中的所有行。使用 --safe-updates
,您只能通过指定标识它们的键值或 LIMIT
子句(或两者)来修改行。这有助于防止意外。安全更新模式还限制了生成(或估计会生成)非常大的结果集的 SELECT
语句。
当 --safe-updates
选项被启用时,mysql 会在连接到 MySQL 服务器时执行以下语句,以设置 sql_safe_updates
、sql_select_limit
和 max_join_size
系统变量的会话值。
SET sql_safe_updates=1, sql_select_limit=1000, max_join_size=1000000;
此 SET
语句对语句处理的影响如下
启用
sql_safe_updates
会导致UPDATE
和DELETE
语句在未在WHERE
子句中指定键约束或提供LIMIT
子句(或两者)的情况下产生错误。例如UPDATE tbl_name SET not_key_column=val WHERE key_column=val; UPDATE tbl_name SET not_key_column=val LIMIT 1;
将
sql_select_limit
设置为 1,000 会导致服务器将所有SELECT
结果集限制为 1,000 行,除非语句包含LIMIT
子句。将
max_join_size
设置为 1,000,000 会导致多表SELECT
语句在服务器估计必须检查超过 1,000,000 行组合时产生错误。
要指定不同于 1,000 和 1,000,000 的结果集限制,可以使用 --select-limit
和 --max-join-size
选项在调用 mysql 时覆盖默认值。
mysql --safe-updates --select-limit=500 --max-join-size=10000
在安全更新模式下,即使在 WHERE
子句中指定了键,UPDATE
和 DELETE
语句也可能会产生错误,如果优化器决定不使用键列上的索引,则会出现这种情况。
如果内存使用量超过
range_optimizer_max_mem_size
系统变量允许的内存使用量,则无法使用索引上的范围访问。然后,优化器将退回到表扫描。请参见 限制范围优化的内存使用。如果键比较需要类型转换,则可能不会使用索引(请参见 第 10.3.1 节“MySQL 如何使用索引”)。假设索引字符串列
c1
使用WHERE c1 = 2222
与数值进行比较。对于此类比较,字符串值将转换为数字,并且操作数将以数字方式进行比较(请参见 第 14.3 节“表达式求值中的类型转换”),从而阻止使用索引。如果启用了安全更新模式,则会发生错误。
安全更新模式中包含这些行为。
EXPLAIN
与UPDATE
和DELETE
语句不会产生安全更新错误。这使得可以使用EXPLAIN
加上SHOW WARNINGS
来查看未使用索引的原因,这在例如range_optimizer_max_mem_size
违规或类型转换发生并且优化器即使在WHERE
子句中指定了键列时也不使用索引的情况下可能会有所帮助。当发生安全更新错误时,错误消息将包含第一个生成的诊断信息,以提供有关失败原因的信息。例如,消息可能表明
range_optimizer_max_mem_size
值已超过或发生了类型转换,这两者都可能阻止使用索引。对于多表删除和更新,仅当任何目标表使用表扫描时,才会在启用安全更新的情况下产生错误。
禁用 mysql 自动重新连接
如果 mysql 客户端在发送语句时丢失了与服务器的连接,它会立即自动尝试重新连接到服务器并再次发送语句。但是,即使 mysql 成功重新连接,您的第一个连接也已结束,并且所有以前的会话对象和设置都将丢失:临时表、自动提交模式以及用户定义和会话变量。此外,任何当前事务都会回滚。此行为可能对您而言很危险,如以下示例所示,在第一个和第二个语句之间服务器已关闭并重新启动,而您并不知道。
mysql> SET @a=1;
Query OK, 0 rows affected (0.05 sec)
mysql> INSERT INTO t VALUES(@a);
ERROR 2006: MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 1
Current database: test
Query OK, 1 row affected (1.30 sec)
mysql> SELECT * FROM t;
+------+
| a |
+------+
| NULL |
+------+
1 row in set (0.05 sec)
当连接丢失时,@a
用户变量已丢失,并且在重新连接后,该变量未定义。如果必须在连接丢失时让 mysql 以错误终止,则可以使用 --skip-reconnect
选项启动 mysql 客户端。
有关自动重新连接及其对重新连接发生时状态信息的影响的更多信息,请参见 自动重新连接控制。
mysql 客户端解析器与服务器解析器
mysql 客户端使用客户端端的解析器,该解析器并非服务器端 mysqld 服务器使用的完整解析器的副本。这会导致某些结构的处理方式不同。示例
如果启用了
ANSI_QUOTES
SQL 模式,则服务器解析器会将用"
字符分隔的字符串视为标识符,而不是普通字符串。mysql 客户端解析器不会考虑
ANSI_QUOTES
SQL 模式。它会以相同的方式处理用"
、'
和`
字符分隔的字符串,无论是否启用了ANSI_QUOTES
。在
/*! ... */
和/*+ ... */
注释中,mysql 客户端解析器会解释简短形式的 mysql 命令。服务器解析器不会解释它们,因为这些命令在服务器端没有意义。如果需要 mysql 不解释注释内的简短形式命令,则部分解决方法是使用
--binary-mode
选项,该选项会导致除非交互模式(对于管道传输到 mysql 或使用source
命令加载)中的\C
和\d
之外,所有 mysql 命令都被禁用。