本节提供有关更有效使用 mysql 的技术以及有关 mysql 操作行为的信息。
输入行编辑
mysql 支持输入行编辑,这使您能够就地修改当前输入行或调用以前的输入行。例如,左箭头 和 右箭头 键在当前输入行中水平移动,而 上箭头 和 下箭头 键在先前输入的行集中向上和向下移动。退格键 删除光标之前的字符,输入新字符将在光标位置输入。要输入该行,请按 Enter。
在 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 客户端,其属性设置为通过控制台与 MySQL 服务器使用 Unicode 通信。
要手动利用此支持,请在使用兼容 Unicode 字体并设置默认字符集为与服务器通信支持的 Unicode 字符集的控制台中运行 mysql
打开一个控制台窗口。
转到控制台窗口属性,选择字体选项卡,然后选择 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 不同的结果集限制,您可以通过在调用 mysql 时使用 --select-limit
和 --max-join-size
选项来覆盖默认值。
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 命令,除了非交互模式下的\C
和\d
(用于管道到 mysql 或使用source
命令加载的输入)。