本节提供了有关使用 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
构建,用户可以在 .editrc
文件中添加以下行,以获得 readline
的行为:
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
文件(请参阅 Controlling the History File),并使用 --histignore="*"
选项启动 mysql 客户端,则交互式历史记录回忆功能将被完全禁用。否则,如果您省略 --histignore
选项,您可以回忆当前会话期间输入的行。
Windows 上的 Unicode 支持
Windows 提供基于 UTF-16LE 的 API 来读取和写入控制台;mysql 客户端可以使用这些 API。Windows 安装程序在 MySQL 菜单中创建一个名为 MySQL 命令行客户端 - Unicode
的项目项。该项目项使用 Unicode 启动 mysql 客户端,以便与 MySQL 服务器通信。
要手动利用该支持,请在使用 Unicode 字符集的控制台中运行 mysql:
-
打开控制台窗口。
-
转到控制台窗口属性,选择字体选项卡,并选择 Lucida Console 或其他兼容的 Unicode 字体。这是必要的,因为控制台窗口默认使用不适合 Unicode 的 DOS 光栅字体。
-
使用 mysql.exe 和
--default-character-set=utf8mb4
(或utf8mb3
)选项执行。这是必要的,因为utf16le
是不能用作客户端字符集之一的字符集。请参阅 Impermissible Client Character Sets。
使用这些更改,mysql 使用 Windows API 与控制台通信,使用 UTF-16LE,并使用 UTF-8 与服务器通信。(之前提到的菜单项设置字体和字符集,如上所述。)
要避免每次运行 mysql 时执行这些步骤,可以创建一个快捷方式,用于调用 mysql.exe。快捷方式应设置控制台字体为 Lucida Console 或其他兼容的 Unicode 字体,并传递 --default-character-set=utf8mb4
(或 utf8mb3
)选项给 mysql.exe。
或者,创建一个快捷方式,仅设置控制台字体,并在 [mysql]
组的 my.ini
文件中设置字符集:
[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: jones@example.com
mail_to: "John Smith" <smith@example.com>
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
,它具有相同的效果)。安全更新模式对于防止意外更新或删除所有表行非常有帮助。通常,这些语句将更新或删除所有表行。使用--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行组合时产生错误。
要指定不同的结果集限制,可以使用--select-limit
和--max-join-size
选项在调用mysql时覆盖默认值:
mysql --safe-updates --select-limit=500 --max-join-size=10000
即使在安全更新模式下,UPDATE
和DELETE
语句也可能在WHERE子句中指定键时产生错误,如果优化器决定不使用键列的索引:
-
如果内存使用超过
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
命令加载)。