Python-MySQL-Shell-入门指南-一-

126 阅读1小时+

Python MySQL Shell 入门指南(一)

原文:Introducing MySQL Shell

协议:CC BY-NC-SA 4.0

一、MySQL Shell 简介

甲骨文继续履行其承诺,让 MySQL 变得更好。这使得 MySQL 工程部门能够在每个新版本中达到更高和更远的目标。最新版本 MySQL 8 包含了比其他版本更多的新特性和增强功能。因此,MySQL 仍然是世界上最受欢迎的开源数据库系统。

为了充分理解 MySQL 8 版本的重要性,让我们考虑一下,虽然 MySQL 过去的版本一直在不断改进产品,但这些版本往往包含一些新功能,重点是改进更受欢迎的功能。因此,以前的版本在很大程度上是渐进的,而不是革命性的。

MySQL 8 在几个方面打破了这一传统。最值得注意的可能是版本号本身。以前的版本是 5。x 范围的数字,但 Oracle 选择使用 8。x 系列标志着技术复杂性的革命性飞跃,并最终脱离了 5 的持续发展。持续了超过 14 年的 x 代码库。

MySQL 8.0 的革命性变化包括致力于高可用性、更高可靠性和复杂性的功能,以及全新的用户体验和革命性的数据处理方式。这本书研究了实现新用户体验的最重要的附加功能之一 MySQL Shell。在这一章中,我们将简要介绍 MySQL 8 的最新特性。但是首先,让我们更好地了解一下 MySQL Shell。

了解 MySQL Shell

许多 MySQL 用户的一个痛点是缺省客户机实用程序的局限性。几十年来,客户机的选择(因为没有其他选择)一直是名为mysql的 MySQL 客户机实用程序,它包含在服务器版本中。

也许旧的 mysql 客户端(MySQL)最大的缺失就是没有任何形式的脚本功能。有人可能会说,用旧客户机来处理一批 SQL 命令,编写 SQL 命令脚本是可能的。其他人可能会指出,MySQL 支持的 SQL 语言对编写存储例程(过程和函数)的支持有限。然而,对于那些想要创建和使用脚本语言来管理他们的数据库(和服务器)的人来说,已经有了外部工具选项,包括 MySQL Workbench 和 MySQL Utilities(现在已经退休了),但是没有专门用于合并脚本语言的工具。

注意

MySQL Workbench 是一个 GUI 工具,设计为基于工作站的工具,具有许多功能,包括设计和建模、开发、数据库迁移等等。参见 http://dev.mysql.com/doc/workbench/en/ 了解更多关于 MySQL Workbench 的信息。

除了这些产品之外,向 MySQL 客户端添加脚本语言的请求还没有得到回应。也就是说,直到现在。

注意

我使用术语“shell”来指代 MySQL Shell 支持的特性或对象。我用“MySQL Shell”来指代产品本身。

概观

MySQL Shell 是 MySQL 的下一代命令行客户端。您不仅可以执行传统的 SQL 命令,还可以使用包括 Python 和 JavaScript 在内的几种编程语言之一与服务器进行交互。此外,如果您还安装了 X 插件,那么您可以使用 MySQL Shell 来处理传统的关系数据以及 JavaScript Object Notation (JSON)文档。这有多酷?

如果你在想,“是时候了!”Oracle 开发了新的 MySQL 客户端,你并不孤单。MySQL Shell 代表了一种大胆的与 MySQL 交互的新方式。有许多选项,甚至有不同的方式来配置和使用 shell。虽然我们将在接下来的章节中看到更多关于 shell 的内容,但是让我们快速地看一下 shell。图 1-1 显示了新 MySQL Shell 的快照。请注意,它提供了一个非常熟悉的界面,尽管更加现代,功能也更加强大。还要注意新的提示。它不仅更加丰富多彩,还提供了一个快速检查,看看你在什么模式。这里显示的是 JS,是 JavaScript 模式(默认模式 1 )。您也可以根据自己的喜好修改提示。

img/478423_1_En_1_Fig1_HTML.jpg

图 1-1

MySQL Shell

小费

如果你想密切关注 MySQL Shell 版本,请加入书签 https://dev.mysql.com/downloads/shell/ ,它包含了流行平台的文档和下载链接。

如果您已经了解到 MySQL Shell 使用全新的机制来访问数据,并且您必须学习所有新的命令,那么您可能已经被引入歧途。虽然 MySQL Shell 确实支持使用脚本语言访问数据的新的应用编程接口(API ),从这个意义上说,还需要学习新的命令(方法),但是 MySQL Shell 继续支持对数据的 SQL 接口。事实上,您所知道的所有 SQL 命令都是完全受支持的。事实上,MySQL Shell 旨在成为您使用离散 SQL 命令的主要工具。

让我们看一个使用 MySQL Shell 和 SQL 命令的例子。图 1-2 显示了一组典型的 SQL 命令,用于创建数据库、插入数据以及选择一些数据进行查看。

img/478423_1_En_1_Fig2_HTML.jpg

图 1-2

使用 MySQL Shell 与 SQL 命令

在这里,我们看到几件事正在发生。首先,我们使用\sql命令将 shell 的模式从 JavaScript 更改为 SQL。然后,我们使用\connect命令连接到服务器。请注意,该命令请求用户密码,如果这是第一次使用该连接,您可以让 shell 为您保存密码(一个很好的安全特性)。从这里,我们可以看到几个运行 SQL 命令的普通例子。清单 1-1 显示了本例中使用的命令。

\sql
\connect root@localhost:3306
CREATE DATABASE testdb;
CREATE TABLE testdb.t1 (a int auto_increment not null primary key, b timestamp, c char(20));
INSERT INTO testdb.t1 (c) VALUES ('one'), ('two'), ('three');
SELECT * FROM testdb.t1 WHERE c = 'two';

Listing 1-1Sample Commands (Getting Started with MySQL Shell)

现在我们已经了解了 MySQL Shell,让我们看看它令人印象深刻的特性列表。你可能会发现有几个可以让你的 MySQL 体验更好。

特征

MySQL Shell 有许多特性,包括支持传统的 SQL 命令处理、脚本原型,甚至支持定制 Shell。下面列出了 shell 的一些主要特性。大多数功能都可以通过命令行选项或特殊的 shell 命令来控制。这个列表是为了让您对 shell 中的特性有一个大致的了解,并且没有给出示例。在后面的章节中,我们将深入探讨一些更重要的特性。

小费

这里的一些术语可能看起来很陌生。在这一点上理解这些并不重要,但是我们将在后面的章节中发现每一个。

  • 自动完成:shell 允许自动完成 SQL 模式下的关键字以及 JavaScript 或 Python 中的所有主要类和方法。只需键入几个字符,然后按TAB键自动完成关键字。当学习新的 API 并试图回忆一个很少使用的 SQL 关键字或 MySQL 函数的拼写时,这可能是一个非常方便的工具。

  • API:Shell 支持 JavaScript 和 Python,与以下应用编程接口交互:

    • X DevAPI :这个 API 允许您使用关系数据或文档存储(JSON)与 MySQL 服务器进行交互。

    • AdminAPI :这个 API 允许您与 MySQL InnoDB 集群进行交互,以设置、配置和维护高可用性集群。

  • 批处理代码执行:如果您想在没有交互会话的情况下运行您的脚本,您可以使用 shell 以批处理模式运行脚本——就像旧客户端一样。

  • 命令历史:shell 保存您输入的命令,允许您使用上下箭头键调用它们。

  • 定制提示:您也可以通过使用特殊格式更新名为~/.mysqlsh/prompt.json的配置文件或定义名为MYSQLSH_PROMPT_THEME的环境变量来更改默认提示。

  • 全局变量:shell 提供了一些全局变量,您可以在使用交互模式时访问这些变量。其中包括以下内容。我们将在第三章中学习更多关于会话和变量的知识。

    • session:全局会话对象(如果已建立)

    • db:通过连接建立的模式

    • dba:用于使用 InnoDB 集群的 AdminAPI 对象

    • shell:使用 Shell 的通用功能

    • util:与服务器一起工作的实用功能

  • JSON 导入:键入 JavaScript 对象符号(JSON)可能会有点繁琐。shell 允许用户将 JSON 文档导入到 shell 中,这使得使用 JSON 变得更加容易。交互式命令和 API 函数中都启用了导入功能。

  • 交互式代码执行:使用 shell 的默认模式是交互式模式,它的工作方式类似于旧的 MySQL 客户端,在这里输入命令并获得响应。

  • 日志:你可以为你的会话创建一个日志,用于以后的分析或者保存消息的记录。您可以使用--log-level选项设置详细程度,范围从 1(无记录)到 8(最大调试)。

  • 多行支持:shell 允许你输入命令,并将它们缓存起来作为单个命令执行。

  • 输出格式:Shell 支持三种格式选项;table ( --table),这是您在旧客户端中习惯使用的传统网格格式,tab(--tabbed),它使用制表符分隔显示信息并用于批处理执行,以及 JSON ( --json),它以更易于阅读的方式格式化 JSON 文档。这些是您在启动 shell 时指定的命令行选项。

  • 脚本语言:shell 支持 JavaScript 和 Python,尽管你一次只能使用一种。

注意

在本书中,我们将重点介绍 Python,但使用 JavaScript 的 API 是相同的。唯一的区别是类和方法是如何拼写的。这是因为 JavaScript 对大写和多字标识符使用了不同的约定。精明的 JavaScript 开发人员翻译本书中的例子不会有问题。

  • 会话:会话本质上是到服务器的连接。shell 允许您处理会话,包括在需要时存储和检索会话。

  • 启动脚本:您可以定义一个脚本在 shell 启动时执行。您可以用 JavaScript 或 Python 编写脚本。

  • 升级检查器(Upgrade Checker): shell 还包括一个方便的升级检查工具,可以让你检查给定的服务器,看看它是否可以升级到 MySQL 8。对于那些将现有 MySQL 服务器迁移到 MySQL 8 的人来说,这是一个真正的时间节省器。

  • 用户凭证“秘密”存储:也许最节省时间的特性是能够将用户密码保存到平台或特定平台存储中常见的“秘密存储”或加密凭证存储机制中。shell 支持 MySQL 登录路径、MacOS keychain 和 Windows API。默认情况下,此功能是打开的,但可以根据用户凭据禁用(如果不想存储密码,可以不存储)。如果您使用单个系统或跨多个系统的受保护帐户,这将通过从 secret store 中取回该用户的密码来节省您的时间。我们将在第三章中看到更多关于这个特性的内容。

MySQL Shell 的最新版本(8.0.16)包括许多错误修复和一些新功能,肯定会受到欢迎并经常使用。其中包括以下内容。

  • 用户自定义报告:您现在可以设置报告来显示来自服务器的实时信息,如状态和性能数据。如果您想监控您的服务器元数据和状态变量,请参见 https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-reporting.html 了解关于此新功能的更多信息。

  • SQL 模式执行:如果你正在使用 JavaScript 模式的 Python 中的 shell,并且想要运行 SQL 命令,那么\sql shell 命令现在允许你指定一个要运行的 SQL 命令。例如,您可以执行\sql SHOW DATABASES,而不必切换到 SQL 模式(或者反过来)。

  • AdminAPI :现在在status()describe()rescan()方法中报告关于服务器版本的信息。

MySQL Shell 并不是 MySQL 8 中唯一的新特性。事实上,MySQL 的最新版本中有很多值得喜欢和探索的地方。事实上,有一些已经改进的特性,像 MySQL Shell 这样引入的新特性,以及一些将改变您使用 MySQL 方式的非常独特的特性。其中一些特性将 MySQL Shell 作为一个关键组件。因为我们计划探索如何在 shell 中使用这些特性,所以让我们花点时间了解一下 MySQL 8 中的新特性。

旧功能再创新

这个类别包括那些在 MySQL 早期版本中作为独立下载或插件引入的特性。有些被认为是实验性的,即使它们可能是在正式发布(g a)期间引入的(该特性可能不是正式发布的)。虽然将来可能会以这种方式引入一些功能,但目前所有这些功能都是 MySQL 8 GA 的一部分,而且形式更加精炼。其中包括以下内容。这里没有列出的是该版本中包含的数百个小到中等的增强和缺陷修复。

  • JSON 数据类型:对数据最具革命性的改变包括加入了 JSON 数据类型,它允许使用 MySQL 作为真正的 NoSQL 数据库系统。

  • X Plugin、X Protocol 和 X DevAPI :服务器现在支持新的客户端协议,所有新的 API 都建立在该协议之上。

  • InnoDB 改进:除了作为默认的存储引擎,InnoDB 已经成为一个更加健壮的企业级原子性、一致性、隔离性和持久性(ACID)兼容的存储引擎。

JSON 数据类型

从 MySQL 版本 5.7.8 开始,MySQL 支持 JSON 数据类型。JSON 数据类型可用于在关系表中存储 JSON 文档。因此,您的表中可以有 JSON 列!在一个表中可以有多个 JSON 列(字段)。

JSON 数据类型也是将 MySQL 用作文档存储的一个关键组件。简而言之,JSON 是一种用于交换数据的标记语言。它不仅可读,还可以直接在应用中使用,在其他应用、服务器甚至 MySQL 之间存储和检索数据。

注意

下面是对 JSON 数据类型和 JSON 文档的简要概述。我们将在第六章看到对 JSON 的深入研究。

事实上,程序员对 JSON 很熟悉,因为它类似于其他标记方案。JSON 也非常简单,因为它只支持两种类型的结构:(1)包含(name,value)对的集合,(2)有序列表(或数组)。当然,您也可以混合和匹配一个对象中的结构。当我们创建一个 JSON 对象时,我们称之为 JSON 文档。 2

与 MySQL 中的普通数据类型不同,JSON 数据类型允许您将 JSON 格式的对象(文档)存储在一行的一列中。虽然您可以对文本或 BLOB 字段这样做(很多人都这样做),但是 MySQL 中没有内置与文本和 BLOB 字段中的数据进行交互的功能。因此,数据的操作在很大程度上取决于应用。此外,数据的结构通常是每行都有相同的列“格式”。在文本和 BLOB 字段中存储数据并不新鲜,很多人已经这样做了很多年。

使用 JSON 数据类型,我们不必编写任何专门的代码来存储和检索数据。这是因为 JSON 文档很好理解,并且许多编程环境和脚本语言本身就支持它。JSON 允许你存储当时的数据。与典型的数据库表不同,我们不必担心默认值(它们是不允许的),也不必担心我们是否有足够的列,甚至是主/从关系来将所有数据规范化并存储在一个漂亮、整洁、结构化的包中。

让我们先来看看 JSON 数据类型。假设您想在数据库中存储地址,但是您不能保证您存储的所有项目都有一个地址,有些可能有多个地址。更糟糕的可能是你掌握的地址信息不一致。也就是说,地址的形式和所提供的数据各不相同。例如,您可能有一行、两行甚至三行“街道”地址,但其他地址可能只有一行带有邮政信箱号码。或者,有些地址包含五位数字的邮政编码,而有些地址包含九位数字的邮政编码,甚至有些地址可能包含邮政编码(如加拿大邮政)。

在这种情况下,您可以将地址字段添加到现有的表中(但这并不能解决行可能有多个地址的情况),或者更好的方法是创建一个关系表来存储地址并将数据硬塞进字段中。对于不符合的地址,您可能会被迫使用缺省值,甚至为缺失的项目存储 NULL。尽管所有这些都是可能的,但它会在关系数据库中增加一层复杂性,这可能意味着需要额外的代码来处理丢失的数据。

图 1-3 显示了一个典型的关系数据库的模式,它包含了作为一个单独的表存储的地址。这段摘录虽然非常简洁和不完整,但展示了数据库设计人员在处理数据(如地址)时采用的典型方法,这些数据可能因项目而异。

img/478423_1_En_1_Fig3_HTML.jpg

图 1-3

示例关系数据库摘录

这种方法没有错,但是为了理解 JSON 数据类型给我们带来的优势,让我们看一组典型的 SQL 语句来创建示例并插入一些数据。清单 1-2 显示了用于创建表格的示例 SQL 语句。我包含了切换到 SQL 模式并连接到服务器的特定于 shell 的命令。

DROP DATABASE IF EXISTS my dB;
CREATE DATABASE mydb;
CREATE TABLE mydb.customers (id int auto_increment NOT NULL PRIMARY KEY, first_name char(30), last_name char(30));
CREATE TABLE mydb.addresses (id int NOT NULL, caption char(20) NOT NULL, street1 char(100), street2 char(100), city char(50), state_code char(2), zip char(10), PRIMARY KEY(id, caption));
INSERT INTO mydb.customers VALUES (NULL, 'Sam', 'Blastone');
SELECT 2483308 INTO @last_id;
INSERT INTO mydb.addresses VALUES (@last_id, 'HOME', '9001 Oak Row Road', Null, 'LaPlata', 'MD', '33532');
INSERT INTO mydb.addresses VALUES (@last_id, 'WORK', '123 Main Street', Null, 'White Plains', 'MD', '33560');
SELECT first_name, last_name, addresses.∗ FROM mydb.customers JOIN mydb.addresses ON customers.id = addresses.id \G

Listing 1-2Sample Relational Database SQL (no JSON)

到目前为止,添加的地址有些正常。但是考虑到我们想要添加另一个地址但是这个地址不完整的可能性。例如,我们只知道这个客户的仓库位置所在的城市和州,我们了解到客户在那里花费了一些时间。我们希望存储这些信息,这样我们就可以知道客户在该地区的存在,但我们可能不知道任何更多的细节。如果我们继续使用这个关系示例,我们将添加几个空字段(这是可以的)。当我们在插入不完整的地址后运行SELECT查询时,我们得到了这个信息。

> SELECT first_name, last_name, addresses.∗ FROM mydb.customers JOIN mydb.addresses ON customers.id = addresses.id \G
...
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
first_name: Sam
 last_name: Blastone
        id: 1
   caption: WAREHOUSE
   street1: NULL
   street2: NULL
      city: Carson Creek
state_code: CO
       zip: NULL

我们最终在一个表(customers)中得到一行,在另一个表(addresses)中得到三行,但是有几个空字段。现在,让我们看看这个例子,只是这次我们将使用 JSON 数据类型来存储地址。

在下一个示例中,我们用 customers 表中分配了 JSON 数据类型的一个列替换了第二个表(address detail 表)。除了明显地删除第二个表和查询数据必须遍历的关系之外,我们还获得了只存储我们需要的内容的能力。清单 1-3 显示了构建这个版本的修改后的 SQL 语句。

DROP DATABASE IF EXISTS mydb_json;
CREATE DATABASE mydb_json;
CREATE TABLE mydb_json.customers (id int auto_increment NOT NULL PRIMARY KEY, first_name char(30), last_name char(30), addresses JSON);
INSERT INTO mydb_json.customers VALUES (NULL, 'Sam', 'Blastone', '{"addresses":[
    {"caption":"HOME","street1":"9001 Oak Row Road","city":"LaPlata","state_code":"MD","zip":"33532"},
    {"caption":"WORK","street1":"123 Main Street","city":"White Plains","state_code":"MD","zip":"33560"},
    {"caption":"WAREHOUSE","city":"Carson Creek","state_code":"CO"}
]}');
SELECT first_name, last_name, JSON_PRETTY(addresses) FROM mydb_json.customers \G

Listing 1-3Sample Relational Database SQL (JSON)

在这里,我们看到定义表的 SQL 缩短了很多。要使用 JSON 数据类型,我们只需指定JSON,在这里我们可以使用任何其他数据类型。然而,输入带有 JSON 值的数据需要更多的输入,但是正如您所看到的,它允许我们使用表达式,用一种容易理解的语言描述代码。查询这些数据会将 JSON 字符串作为单个字符串返回,但是我们可以使用 MySQL JSON 函数之一来帮助提高输出的可读性。为此,我们使用清单 1-4 中所示的JSON_PRETTY()函数,它在从服务器返回的字符串中放置换行符和空格。

> SELECT first_name, last_name, JSON_PRETTY(addresses) FROM mydb_json.customers \G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
            first_name: Sam
             last_name: Blastone
JSON_PRETTY(addresses): {
  "addresses": [
    {
      "zip": "33532",
      "city": "LaPlata",
      "caption": "HOME",
      "street1": "9001 Oak Row Road",
      "state_code": "MD"
    },
    {
      "zip": "33560",
      "city": "White Plains",
      "caption": "WORK",
      "street1": "123 Main Street",
      "state_code": "MD"
    },
    {
      "city": "Carson Creek",
      "caption": "WAREHOUSE",
      "state_code": "CO"
    }
  ]
}
1 row in set (0.0036 sec)

Listing 1-4Querying Rows with JSON Data

注意,我们现在只有一个表,地址已经“折叠”到 JSON 列中,每一行都存储地址数组。并且,只存储已知的数据。因此,对于仓库地址,我们只存储城市和州。虽然在 shell 输出中不容易阅读(稍后我们将看到一些提高输出格式可读性的方法),但我们仍然可以很容易地看到数据。而且,在我们的应用中使用时,接收 JSON 将比检查每一列的数据容易得多。我们将在第六章中了解更多。

正如我们所发现的,JSON 数据类型使得我们的数据存储更加灵活。正如我们将在第六章中发现的那样,我们可以通过 X 插件、X 协议和 X DevAPI,借助内置于 MySQL 和 MySQL Shell 中的支持,使用文档存储将我们所有的数据存储为 JSON 文档,从而进一步发展这个概念。事实上,现在让我们通过研究新的 X 插件和 X 协议来发现是什么让 shell 变得强大。

X 插件、X 协议和 X DevAPI

MySQL 引入了新的协议和 API 来处理 JSON 文档。除了支持 JSON 数据类型,我们还有三种以简单名称“X”为前缀的技术:X 插件、X 协议和 X DevAPI。X 插件是一个启用 X 协议的插件。X 协议被设计成使用 X DevAPI 与服务器通信。X DevAPI 是一个应用编程接口,它允许您为 MySQL 开发 NoSQL 解决方案,并将 MySQL 用作文档存储。我们将在后面的小节中了解更多关于文档存储的内容。

您可能想知道 shell 和插件是如何与服务器交互的。图 1-4 显示了组件是如何“堆叠”的。

img/478423_1_En_1_Fig4_HTML.jpg

图 1-4

x 协议栈

注意,我们有一个允许使用 X DevAPI 的 shell,它通过 X 插件与服务器进行通信。因此,X 插件是一种使能技术,真正的力量是 X 协议和 X DevAPI。

现在我们已经了解了将 MySQL 用作文档存储的技术,让我们看看 InnoDB 存储引擎在最近的版本中有什么变化。

InnoDB 改进

自 MySQL 5.6 以来,InnoDB 一直是 MySQL 的旗舰存储引擎(也是默认引擎)。Oracle 已经慢慢脱离了多存储引擎模型,专注于现代数据库服务器应该做的事情—支持事务存储机制。InnoDB 是满足这一需求的答案。

什么是存储引擎?

存储引擎是一种以各种方式存储数据的机制。例如,有一种存储引擎允许您与逗号分隔值(文本)文件(CSV)进行交互,另一种为写日志文件(归档)进行了优化,一种只在内存中存储数据(内存),甚至还有一种根本不存储任何东西(黑洞)。您可以通过使用 ENGINE = table 选项将它们用于您的表。除了 InnoDB,MySQL 服务器还附带了 Archive、Blackhole、CSV、Memory 和 MyISAM 存储引擎。InnoDB 存储引擎是唯一支持事务的引擎。有关其他存储引擎的更多信息,包括每个引擎的功能及其使用方法,请参见在线参考手册中的“备用存储引擎”一节。

在早期,InnoDB 是一家独立的公司,因此它是一款独立的产品,既不是 MySQL 的一部分,也不属于 MySQL AB(MySQL 的最初所有者,现在完全归 Oracle 所有)。最终,Oracle 同时拥有了 InnoDB 和 MySQL,因此将两者结合起来是有意义的,因为它们具有相互包容的目标。虽然仍然存在一个独立的 InnoDB 工程团队,但他们已经与核心服务器开发团队完全集成。

这种紧密的集成带来了 InnoDB 的许多改进,包括许多性能增强,甚至支持微调等等。这一点在 InnoDB 不断改进的过程中显而易见,尤其是 MySQL 8 中的 InnoDB。

虽然大多数改进都相当微妙,从某种意义上说,你不会注意到它们(除了通过更好的性能和可靠性,这是不可轻视的),但大多数都显示出致力于使 InnoDB 成为最佳的事务存储机制,并通过扩展 MySQL 成为强大的事务数据库系统。

最显著的改进包括性能和稳定性。同样,对于较小的数据库,您可能看不到太多的差异,但是较大的数据库和企业级系统将会看到显著的改进。例如,崩溃恢复和日志记录得到了相当大的改进,使得恢复更快,正常关机和启动也更快。

类似地,死锁检测、临时表、自动增量甚至 Memcached 支持方面的改进表明了 Oracle 想尽一切办法纠正缺陷和改进 InnoDB 的愿望。虽然这个列表似乎集中在小的改进上,但是其中一些对于寻求帮助调优和规划数据库服务器安装的系统管理员来说非常重要。

小费

如果您想了解更多关于这些改进的信息或查看所有最新变化的列表,请参见在线 MySQL 8 参考手册( http://downloads.mysql.com/docs/refman-8.0-en.pdf )。

下一节将描述 MySQL 8 新增的和独有的特性。

新功能

除了那些在 5.7 服务器版本中开发的特性之外,还有一些 MySQL 8 独有的特性。它们目前还没有(甚至不可能被合并到)旧版本中。这部分是因为服务器代码库为了适应新特性而做了大量的修改。MySQL 8.0 中的新特性包括:

  • 数据字典:系统中所有对象的事务性元数据存储机制

  • 账户管理:用户、密码、权限管理的重大改进

  • 删除的选项、变量和特性:希望从旧版本升级的用户应该查看新版本中有所变化的较小细节,例如删除的选项、变量和特性

除了那些在 5.7 服务器版本中开发的特性之外,还有一些 MySQL 8 独有的特性。事实上,它们目前还没有(甚至不可能被合并到)旧版本中。这部分是因为服务器代码库为了适应新特性而做了大量的修改。MySQL 8.0 中的新特性包括新的数据字典和新的账户管理系统。

数据字典

如果您曾经使用 MySQL 试图获取数据库中包含的对象的信息,或者发现那里有什么对象,搜索具有特定名称前缀的对象,或者试图发现存在什么索引,那么您很可能必须访问INFORMATION_SCHEMA中的表和视图,或者必须导航的特殊的mysql数据库。也许最糟糕的是一些表格的定义被存储在一个特殊的结构化文件中,叫做.frm 3 (表单)文件。例如,database1中一个名为table1的表格有一个名为/data/database1/table1.frm.frm文件。

注意

INFORMATION_SCHEMAmysql数据库仍然可见,这些视图和表格中的信息仍然可以在数据字典之前以类似的方式使用,但是缺少数据字典中的附加信息。

这种组合要求数据库管理员通过了解数据所在的位置来学习如何查找数据。根据您要查找的内容,您可能需要查询某个数据库,或者在可怕的情况下,破译.frm文件。更重要的是,由于数据是在非事务性的表(和元数据文件)中,所以这些机制不是事务性的,并且,通过扩展,不是崩溃安全的。

新的数据字典改变了这一切,使我们可以创建一个单一的事务性(与 InnoDB 相同的 ACID 支持)存储库来存储系统中对象的所有元数据。所有基于文件的元数据已经被移动到数据字典中,包括.frm文件、分区、触发器和其他选项文件(例如.par.trn.trg.isl.opt)。

但是,您不会在数据库列表中看到数据字典(例如,SHOW DATABASES)。数据字典表是不可见的,不能直接访问。您不会很容易找到数据字典表(尽管如果您足够努力的话是有可能的)。

这样做主要是为了使数据字典崩溃安全,并且您不必进行管理。幸运的是,您可以通过INFORMATION_SCHEMA数据库甚至是SHOW命令来访问存储在数据字典中的信息。mysql 数据库仍然存在,但它主要包含额外的信息,如时区、帮助和类似的非重要信息。事实上,INFORMATION_SCHEMASHOW命令使用数据字典来表示信息。

那么,看不到数据字典怎么用呢?简单地说,INFORMATION_SCHEMA视图从数据字典中获取信息。因此,您可以继续使用您习惯使用的相同查询,但是在这种情况下,数据更加可靠和具有事务性。酷!

有关数据字典的更多信息,包括存储了什么以及它如何与INFORMATION_SCHEMA视图交互的细节,请参见在线 MySQL 参考手册( https://dev.mysql.com/doc/refman/8.0/en/ )中的“MySQL 数据字典”一节。

添加数据字典最终使得许多人一段时间以来一直想实现的几个特性成为可能。最新的一项是对账户管理的重大改革。

账户管理

MySQL 数据库管理员(尤其是那些使用企业级系统的管理员)的另一个棘手问题是需要为一组用户分配相同的权限并管理密码。MySQL 8 在帐户管理和 MySQL 中的特权系统方面提供了许多改进。下面列出了最重要的改进。

  • 角色:管理员可以将授权语句分配给一个角色,该角色可以分配给多个用户。

  • 用户帐户限制:管理员可以设置资源限制,帮助限制对关键数据的访问。

  • 密码管理:管理员可以设置密码形成和失效的条件。

  • 用户账户锁定:管理员可以暂时锁定用户账户,禁止其访问数据。

注意

MySQL 8 禁止使用GRANT语句创建用户帐户。您必须首先使用CREATE USER语句显式创建用户。

角色

一个非常常见的场景是必须创建一组具有相同权限的用户。过去,您必须保存或存档GRANT语句,并为每个用户重复这些语句。也就是说,您可以为两个或更多用户重用GRANT语句。幸运的是,随着数据字典的出现,MySQL 中的支持角色在 MySQL 8 中已经成为现实!

可以创建、删除角色,授予或撤销权限。我们还可以向用户授予角色或从用户处撤销角色。角色最终使得管理 MySQL 上的用户账户变得更加简单。

用户帐户限制

企业系统的另一个管理问题包括需要在特定时间段内进一步限制对用户帐户的访问,或者甚至限制帐户发出特定数量的语句。

在 MySQL 8 中,管理员可以为用户帐户设置每小时查询数、每小时事务数、每小时连接数,甚至每小时同时连接数的限制。这允许管理员为安全目标、工作效率限制等设置限制。

密码管理

帐户管理功能中最受欢迎的变化之一是设置密码限制和标准的能力。在当今充满挑战的安全环境中,我们必须确保我们的密码不会被轻易破解,为此,我们需要控制密码的长度以及包含多少小写或大写字符或特殊字符。

幸运的是,MySQL 8 有这些功能,你可以设置密码有效期,旧密码限制的重用,密码的验证,当然还有密码强度。这些功能和前面提到的两个功能帮助推动 MySQL 8 在更好的安全性方面向前迈出了一大步。

用户帐户锁定

有时,您必须暂时限制对一个或多个用户帐户的访问。这可能是由于维护计划、诊断,甚至是员工的临时休假。不管是什么原因,MySQL 在过去要么需要更改密码(并且不告诉用户——但这并不阻止帐户被使用),要么删除帐户并在以后重新创建它。如果您的用户帐户被授予了复杂的权限(或几个角色),这是有问题的。

MySQL 8 包含一个特性,支持使用ACCOUNT LOCK子句锁定帐户和使用ACCOUNT UNLOCK子句解锁帐户来锁定和解锁用户帐户。您可以在CREATE USER语句或ALTER USER语句中使用这些子句。

帐户管理功能还有许多小的改进。要了解更多有关变更的信息,请参阅在线参考手册中的“用户帐户管理”一节( https://dev.mysql.com/doc/refman/8.0/en/ )。

删除了选项、变量和功能

如果您阅读了 MySQL 8 的发行说明,您可能会注意到 MySQL 8 对启动选项、变量等进行了许多小的更改。可以在 https://dev.mysql.com/doc/relnotes/mysql/8.0/en/ 找到 MySQL 8 每个版本所有变更的完整列表。

幸运的是,大多数变化都与支持最新功能和删除旧的和过时的设置有关。所以,大多数不会对那些想开始使用 MySQL 的人有太大影响。但是,从旧版本升级时,有几个问题可能不太重要。

请记住,在 MySQL 5.7(及更早版本)中,许多选项、变量和特性都被标记为不推荐使用。它们现在在 MySQL 8 中被正式移除。如果您使用 MySQL 已经有一段时间了,那么您很可能已经为这些变化做好了准备。

然而,有一些变化可能会影响一些想升级到 MySQL 8 的人。其中包括以下内容。

  • 删除了--bootstrap选项。它用于控制服务器如何启动,通常用于创建 MySQL 特权表,而无需启动完整的 MySQL 服务器。

  • --innodb_file_format_∗选项已更改。这些用于配置 InnoDB 存储引擎的文件格式。

  • 删除了--partition--skip分区选项。它们用于控制 MySQL 服务器中用户定义的分区支持。

  • 作为数据字典功能的一部分,.frm和相关元数据文件被删除。

  • 一些 SSL 选项已经改变,并且引入了新的认证插件(caching_sha2_password)来提高安全连接。

  • 在最新版本中,许多错误代码都进行了更改,包括删除了几十个鲜为人知的错误代码。如果您的应用使用 MySQL 服务器错误代码,您应该检查文档以确保错误代码没有被更改或删除。

像这样的变化是主要版本的典型特征。在任何情况下,您都应该在计划任何升级时考虑发行说明。像这样的更改可能会导致问题的地方是在您的定制和配置中。例如,如果您已经定义了使用选项和变量或与之交互的调优过程、存储过程、DevOps 或其他机制,您应该仔细检查 MySQL 8 文档中的条目,以确保您可以相应地修改您的工具。

小费

参见 http://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html 获取 MySQL 8 中要删除的特性的完整列表。

范式转变特征

MySQL 8 中的一些特性对于 MySQL 生态系统来说确实是开创性的。事实上,它们可能会改变人们使用 MySQL 的方式,并扩展 MySQL 日益增长的用例列表。这些包括以下范式转变特征。

  • 文档存储:一种新的结构化存储机制,它将改变您可以存储的内容,以及您与 MySQL 交互的方式,从而为数据可能发生变化的应用存储数据,使您的应用无需重新构建存储层即可适应变化

  • 组复制:一种新的、强大的自我修复高可用性选项

  • InnoDB Cluster :一种新的管理高可用性的方法,建立在组复制的基础上,结合了新的 shell 和 MySQL 路由器,实现了易于设置和维护的高可用性安装

文档存储

在讨论 JSON 数据类型时,我们已经了解了一些关于文档存储的知识。MySQL 文档存储将 JSON 存储概念带到了一个新的高度。虽然 JSON 数据类型允许在我们的关系数据库中引入非结构化数据,但是文档存储是真正的 NoSQL 数据存储。

更具体地说,文档存储允许在 MySQL 中以 JSON 文档的形式存储非结构化数据。也就是说,MySQL 现在支持 SQL 和 NoSQL 选项。NoSQL 选项使用我们之前发现的 X 技术,包括 X 协议和 X DevAPI。这些允许您编写直接与 MySQL 接口的应用,而不使用任何 SQL 或关系结构。多酷啊。

我知道 SQL,但是 NoSQL 是什么?

如果您曾经使用过关系数据库系统,那么您无疑非常熟悉结构化查询语言(SQL ),在 SQL 中,我们使用特殊的语句(命令)来与数据进行交互。事实上,大多数数据库系统都有自己的 SQL 版本,包括操作数据的命令(DML)以及定义存储数据的对象的命令(DDL ),甚至包括管理服务器的管理命令。

也就是说,您获得结果集,并且必须使用命令来搜索数据,然后将结果转换为内部编程结构,使数据看起来像是一个辅助组件,而不是解决方案的一个组成部分。NoSQL 接口打破了这种模式,它允许您使用 API 来处理数据。更具体地说,您使用编程接口,而不是基于命令的接口。

遗憾的是,NoSQL 可能意味着几件事,这取决于你的观点,包括“非 SQL”,“不仅仅是 SQL”,或者“非关系”。但是它们都是指这样一个事实,即你所使用的机制并没有使用基于命令的接口,而且这个术语的大多数用法都表明你使用的是编程接口。对于 MySQL 8,可以通过 SQL 或 NoSQL 使用 X 协议访问 JSON 文档,通过 X 插件访问 X DevAPI。

MySQL 文档存储库的起源在于几种技术,它们被结合在一起形成了文档存储库。具体来说,Oracle 将键、值机制与新的数据类型、新的编程库和新的访问机制结合起来,创建了现在的文档存储。这不仅允许我们使用带有 NoSQL 接口的 MySQL,还允许我们构建混合解决方案,利用关系数据的稳定性和结构,同时增加 JSON 文档的灵活性。

我们将在第六章中了解更多关于文档存储的信息。

组复制

如果您使用过 MySQL 复制,那么您无疑非常熟悉如何在构建高可用性解决方案时利用它。事实上,您很可能已经发现了许多使用 MySQL 复制来提高应用可用性的方法。

此外,显而易见的是,您的高可用性需求越多,您的解决方案越扩展(越复杂),您就越需要采用更好的方法来管理节点丢失、数据完整性和集群的一般维护(复制数据的服务器组,有时称为副本集)。事实上,大多数高可用性解决方案已经超越了基本的主从拓扑结构,演变成由服务器集群组成的层,一些服务器复制一部分数据以获得更快的吞吐量,甚至用于分区存储。所有这些导致许多人发现他们需要更多的 MySQL 复制。Oracle 通过组复制满足了这些需求以及更多需求。

通过组复制,您可以建立一组要在组中使用的服务器,这不仅可以减少服务器之间的事务,还可以实现自动故障转移和容错。此外,组复制还可以与 MySQL 路由器一起使用,以允许您的应用拥有一个与集群隔离的层。当我们研究 InnoDB 集群时,我们将会对路由器有所了解。

组复制和标准复制的一个重要区别是,组中的所有服务器都可以参与更新数据,并自动解决冲突。是的,您不再需要精心设计您的应用来发送写入(更新)到特定的服务器!但是,您可以将组复制配置为只允许一台服务器(称为主服务器)进行更新,其他服务器充当辅助服务器或备份服务器(用于故障转移)。

我们将在第八章中了解更多关于组复制的信息。

InnoDB 集群

另一个新出现的特性叫做 InnoDB 集群。它旨在使高可用性更易于设置、使用和维护。InnoDB Cluster 通过 MySQL Shell 和 AdminAPI、组复制和 MySQL 路由器与 X AdminAPI 协同工作,将高可用性和读取可伸缩性提升到一个新的水平。也就是说,它将 InnoDB 中用于克隆数据的新功能与组复制、MySQL Shell 和 MySQL 路由器相结合,提供了一种设置和管理高可用性的新方法。

注意

AdminAPI 是一个特殊的 API,可通过 MySQL Shell 进行配置并与 InnoDB 集群交互。因此,AdminAPI 具有旨在简化 InnoDB 集群工作的特性。

在此使用案例中,群集设置有一个主节点(在标准复制术语中称为主节点),它是所有写入(更新)的目标。多个辅助服务器(从属服务器)维护数据的副本,这些副本可以被读取,因此能够在不给主服务器增加负担的情况下读取数据,从而实现读取可伸缩性(但是所有服务器都参与协商和协调)。组复制的引入意味着集群是容错的,并且组成员是自动管理的。MySQL 路由器缓存 InnoDB 集群的元数据,并执行到 MySQL 服务器实例的高可用性路由,从而更容易编写应用来与集群进行交互。

您可能想知道这与使用标准复制的读出可伸缩性设置有何不同。从高层次来看,这些解决方案似乎正在解决同一个用例。但是,使用 InnoDB Cluster,您可以从 MySQL shell 创建、部署和配置集群中的服务器,从而提供一个易于管理的完整的高可用性解决方案。也就是说,您可以通过 shell 使用 InnoDB Cluster AdminAPI,使用 JavaScript 或 Python 以编程方式创建和管理 InnoDB 集群。

我们将在第十章中了解更多关于 InnoDB 集群的信息。

摘要

MySQL 8 有很多新特性。在许多方面,它代表了包括高可用性和 NoSQL 在内的几个领域的重大飞跃。然而,一个宣传较少但非常重要的新特性是新的 MySQL Shell。正如您将在接下来的章节中看到的,新的 Shell 是使所有新特性以无缝方式一起工作的粘合剂。

例如,如果没有 shell,使用 MySQL 文档存储将需要使用第三方编程环境来与 X DevAPI 交互。shell 使得使用新的 API 变得更加容易,因为它不仅提供了一个熟悉的环境(想想旧的客户机),而且对用户更加友好。

类似地,如果没有实现 AdminAPI 的 shell,使用 InnoDB Cluster 不会比 MySQL 复制所需的手动管理更好。虽然您仍然可以手动配置 MySQL 中的任何高可用性特性,但现在我们有了 shell 来使这一切变得更加容易,除非在某些特定的情况下,否则没有必要这样做。

然而,要真正理解 shell 对 MySQL 8 的重要性和重大贡献,我们必须看到它在每个新特性中的表现。本书的其余部分将介绍使用 MySQL 8 中每个主要特性的简短教程,以及如何使用 shell 实现该特性的示例。其中包括以下内容:

  • 对 SQL 数据库使用 shell

  • 将 Shell 与文档存储一起使用

  • 将 shell 用于组复制

  • 将 shell 与 InnoDB 集群一起使用

但是首先,我们将在下一章看到如何安装 MySQL Shell。

Footnotes 1

这可能是关于 shell 不支持 SQL 的谣言的来源——默认模式是 JavaScript,但是正如你所看到的,SQL 也是受支持的。我们将在下一章看到如何设置启动模式。

  2

可以把 JSON 看作是 XML 文档的派生或扩展。也就是说,它们提供了一种灵活的方式来存储可能因条目而异的数据。

  3

那个。当文件丢失或损坏时,frm 文件已经成为可怕困难的来源。

 

二、安装 MySQL Shell

虽然 MySQL 服务器仍然包含旧的 MySQL 客户端(mysql),但是新的 MySQL Shell 应该被视为与 MySQL 服务器交互的默认客户端。它比之前与服务器捆绑的客户端有很多优势;最强大的是直接从 shell 中使用 Python 或 JavaScript 的能力。那么,我们如何获得新的 MySQL Shell 呢?

在这一章中,我们将发现如何为三个最流行的平台下载和安装 MySQL ShellWindows、macOS 和 Linux。对于 Windows,我们将使用一个特殊的一体化安装程序,使安装任何 MySQL 产品变得容易。对于 macOS,我们将看到如何使用 macOS 友好的安装程序下载和安装 shell。对于 Linux,我们将了解如何使用 Oracle 的高级打包工具(APT)库来简化在 Linux 上添加 MySQL 产品。

让我们从下载 MySQL Shell 并检查其先决条件开始。

准备安装 MySQL Shell

MySQL Shell 可以安装在 Oracle 支持 MySQL Server 的任何平台上。在大多数平台上,shell 包含在单独的安装中。一个例外是 Windows 平台,其中的 shell 包含在 MySQL Windows Installer 中。在这一节中,我们将看到为各种平台下载 shell 的快速概述。

先决条件

如果您没有安装 MySQL Server 8.0,您可能希望在完成本教程之前在您的系统上安装它。虽然您可以在旧版本的 MySQL 上使用 shell,但是您需要最新版本的服务器才能使用所有功能。

除了在一个系统(或者用于实验或开发目的的台式机或笔记本电脑)上安装 MySQL Server 8.0 之外,shell 还要求您安装以下软件。

注意

对于本书中的示例,您只需要安装 Python 和 Connector/Python。检查您的系统,看看您是否安装了其中的一个。注意,在 Windows 上,可以将 Connector/Python 与 shell 一起安装。

现在让我们看看如何从 Oracle 网站下载 MySQL Shell。

如何获得 MySQL Shell

像大多数 MySQL 产品一样,MySQL Shell 有社区版和企业版。社区版是开源的,因此可以免费下载和使用。如果您是 Oracle 企业客户,您可以通过首选的客户渠道获得 MySQL 的安装程序。但是,如果您愿意,也可以免费下载社区版。在本节中,我们将了解如何下载社区版。

要下载任何 MySQL 产品的社区版,请访问甲骨文的 MySQL 下载页面 https://dev.mysql.com/downloads/ 。在这里,您将看到所有产品的列表。

单击您想要下载的产品( https://dev.mysql.com/downloads/shell/ ),网站将为您提供适用于您的操作系统的可供下载的文件。也就是说,网站会预先选择运行浏览器的操作系统。例如,如果你正在运行 macOS 并点击 MySQL Shell,你会看到如图 2-1 所示的文件列表。如果愿意,您可以单击选择操作系统下拉控件并选择不同的操作系统。

img/478423_1_En_2_Fig1_HTML.jpg

图 2-1

下载 MySQL Shell (macOS)

如果您使用的是 Windows,您可以选择不同的选项。对于 Windows,Oracle 提供了一个全面的指导安装程序,称为 MySQL Installer for Windows。如果您访问任何 MySQL 产品的下载网站,您将在文件列表的顶部看到 MySQL 安装程序的条目。如果您愿意,您仍然可以下载单独的安装程序,但是推荐的机制是使用 MySQL 安装程序。

要下载 MySQL 安装程序( https://dev.mysql.com/downloads/installer/ ,点击所示链接。这将把你带到如图 2-2 所示的另一个页面,该页面显示了可供下载的文件。选择与您的系统相匹配的链接(32 位或 64 位)。

img/478423_1_En_2_Fig2_HTML.jpg

图 2-2

下载 Windows 版 MySQL 安装程序

如果您想继续观看安装程序的运行,请确保为您的 Windows 系统选择正确的下载选项并立即下载。

Windows 版 MySQL 安装程序有两个版本;一个包含通常安装的产品,另一个 web 版本只下载您想要安装的产品。如果你只想安装几个产品,网页版可能是更好的选择。另一方面,如果您打算安装服务器和 shell 以及文档和连接器,您应该下载完整版本。

现在让我们看看如何在 Windows、macOS 和 Linux (Ubuntu)上安装 shell。您可以阅读与您选择的平台相匹配的部分。

使用 MySQL 安装程序在 Windows 上安装

用 MySQL Installer for Windows 安装 MySQL Shell,也就是 MySQL Installer 或简称 Installer,遵循了在 Windows 上安装应用的类似模式。MySQL 安装程序包括所有的 MySQL 产品,允许您安装您想要的组件。虽然 MySQL 安装程序是 Windows 的推荐安装选项,但是您可以下载 shell 并单独安装。但是最好使用 Windows installer。

在本演示中,我们还将安装 MySQL 服务器和使用本书中示例的 shell 的最小组件。您可能希望在您的系统上安装 MySQL。如果您已经安装了 MySQL Server,您可以跳过安装服务器的部分。

当您第一次启动安装程序时(随后的启动将显示添加、修改、升级对话框),您将看到一个显示许可证的欢迎对话框。您必须接受许可证才能继续。图 2-3 显示了安装人员的欢迎面板。

img/478423_1_En_2_Fig3_HTML.jpg

图 2-3

安装人员欢迎面板-许可协议

要接受许可条款,勾选复选框,然后单击下一个的继续。这将使您转到安装类型对话框,您可以在其中选择几个选项之一,包括安装典型开发人员安装的预设、仅安装服务器、仅安装客户端或自定义安装。如果要安装多个产品或删除一些产品,应该使用自定义安装类型。图 2-4 显示了选择设置类型对话框。

img/478423_1_En_2_Fig4_HTML.jpg

图 2-4

选择安装类型

由于我们将安装 MySQL 服务器以及 MySQL Shell 和相关组件,您应该勾选自定义安装类型并点击下一步。这将显示“选择产品和功能”对话框。在这里,我们将选择要安装的组件。对于本教程,我们必须安装以下组件。

  • MySQL 服务器

  • MySQL Shell

  • MySQL 路由器

  • 连接器

  • 连接器/Python

  • MySQL 文档

  • 样本和示例

  • (可选)MySQL 工作台

我们使用自定义选项,因为其他选项将包括我们可能不需要的附加组件(但安装它们不会有什么坏处)。

图 2-5 显示了选择产品和功能对话框。该对话框显示两列,其中左边的一列包含安装程序中的所有产品,右边的一列是选择要安装的产品。

img/478423_1_En_2_Fig5_HTML.jpg

图 2-5

选择产品和功能(默认选择)

要从安装中删除组件,请选择右侧的产品,然后单击向左箭头图标。这将删除产品。要添加产品,只需导航左侧的树找到组件(例如,MySQL Shell),选择它,然后单击绿色箭头将其添加到右侧的列中。图 2-6 显示了正确的选择。

小费

要删除所有组件,请单击双左箭头。同样,要添加所有组件,请单击双右箭头。

img/478423_1_En_2_Fig6_HTML.jpg

图 2-6

选择产品和功能(选定的组件)

当上面列出的所有组件都添加到右边的栏中后,点击下一个按钮继续。这将显示安装对话框面板,其中列出了要安装的组件以及是否必须下载该组件。这是安装程序的一个常见误解。虽然它涵盖了所有组件,但在您下载安装程序时,它可能不包括所有组件。幸运的是,这意味着我们可以只下载那些我们想安装的组件,仅此而已。图 2-7 显示安装对话框。

花点时间检查列表,以确保您已经将所有要安装的组件放在队列中。如果需要进行更改,可以点击返回按钮返回上一个对话框并选择缺少的组件。

img/478423_1_En_2_Fig7_HTML.jpg

图 2-7

安装(暂存)

当您准备好继续时,单击执行按钮。这不会显示一个新的对话框,相反,您会看到每个组件的状态随着下载和安装而变化。图 2-8 显示了正在进行组件安装的对话框的典型示例。

img/478423_1_En_2_Fig8_HTML.jpg

图 2-8

安装(进行中)

一旦所有组件安装完毕,安装对话框面板将显示所有安装完成的状态,并将底部的按钮改为显示下一个,如图 2-9 所示。准备就绪后,一旦所有产品安装完毕,点击下一步

img/478423_1_En_2_Fig9_HTML.jpg

图 2-9

安装(安装完成)

点击下一个的*,出现如图 2-10 所示的产品配置对话框。此时,在配置完每个组件后,安装程序将返回到此对话框。*

img/478423_1_En_2_Fig10_HTML.jpg

图 2-10

产品配置

请注意,我们有三个组件需要配置;服务器、路由器和示例。安装程序将按顺序执行这些操作。只需点击下一步即可开始配置服务器。图 2-11 显示了配置服务器的第一步——设置组复制。

选项包括正常安装组复制(通过选择独立选项)或在沙盒中安装组复制。如果您想在系统上测试组复制,并且不想安装额外的服务器,沙盒选项可能会有所帮助。除了这种情况,您应该始终选择独立选项。

img/478423_1_En_2_Fig11_HTML.jpg

图 2-11

组复制

勾选独立选项,然后点击下一个的*。这将显示如图 2-12 所示的类型和联网对话框。*

img/478423_1_En_2_Fig12_HTML.jpg

图 2-12

类型和网络

在此对话框中,您可以使用一个预配置的选项或用法集,如开发(例如,开发机器)、带应用的服务器或专用服务器(仅安装了 MySQL)。对于笔记本电脑或台式机上的大多数安装,您应该选择开发计算机选项。

如果您想要使用默认的监听端口(3306 和 33060)、命名管道或共享内存,请选择开发计算机选项。如果没有勾选 Windows 防火墙选项,您需要勾选以确保 MySQL 正确运行,并且您可以在 Windows 上连接到它。当您对所有设置满意后,点击下一步。这将显示“验证方法”对话框。

“身份验证方法”对话框允许您选择最新选项,包括强密码加密(强烈推荐)或使用旧的身份验证方法(不推荐用于生产)。

注意

如果您选择强密码加密方法,并希望使用 MySQL 客户端的旧版本(而不是 shell),您可能会遇到连接错误。您必须使用带有强密码加密的新客户端。

图 2-13 显示了认证方法对话框。请注意,有大量的文本描述每个选项,默认情况下使用强密码加密。

img/478423_1_En_2_Fig13_HTML.jpg

图 2-13

认证方法

您应该勾选强密码加密选项,然后单击下一步。这将显示“帐户和角色”对话框。此对话框用于设置 root 密码,并可以选择创建您想要使用的任何角色。如果您计划设置一个服务器供应用和许多用户使用,这可能会很有帮助。但是,在本演示中,我们只需要选择一个 root 密码。

由于我们使用强密码和加密选项,我们在对话框中输入的密码将根据最佳实践(强密码)进行评估。然而,在我们配置服务器使用密码验证插件之前,我们可以使用任何我们想要的密码。无论你是否安装了插件,最好使用强密码。

小费

参见 https://dev.mysql.com/doc/refman/8.0/en/password-management.html 来设置密码选项和验证。

图 2-14 显示了账户和角色对话框。继续键入您选择的 root 用户密码,然后在重复对话框中再次键入。请注意密码强度显示。在这种情况下,我的 10 个字符的密码只有中等强度,尽管使用了特殊字符,没有字典中的单词。苛刻,是吧?

img/478423_1_En_2_Fig14_HTML.jpg

图 2-14

客户和角色

输入 root 密码后,点击下一步的*。这将显示 Windows 服务对话框,我们可以在其中选择在 Windows 上启动服务器并将其作为服务运行。图 2-15 显示了窗口服务对话框。*

img/478423_1_En_2_Fig15_HTML.jpg

图 2-15

Windows 服务

这里建议使用默认选择,包括将 MySQL Server 配置为名为 MySQL80 的 Windows 服务,在启动时启动服务器,使用系统用户启动服务器。但是,如果您想更改这些,并且您熟悉如何在 Windows 上手动启动 MySQL,您可以进行这些更改。

准备好后,点击下一个按钮。这将显示“应用配置”对话框。在这个对话框中没有什么可选择的,所以准备好之后,只需点击执行按钮。这将启动配置过程,以绿色复选标记的形式提供反馈,每个步骤完成后都会出现。

所有步骤完成后,将显示“完成”对话框。图 2-16 显示了完成对话框。点击完成开始下一阶段的配置(MySQL 路由器)。这将返回到产品配置对话框(为简洁起见省略-参见图 2-10 )。

img/478423_1_En_2_Fig16_HTML.jpg

图 2-16

服务器配置完成

在产品配置对话框中,单击下一个的进入 MySQL 路由器配置对话框,该对话框允许您更改路由器的安装方式及其监听的端口。虽然我们没有讨论过路由器,但有些内容可能并不熟悉。幸运的是,缺省值是可以接受的,并且包括用于经典客户机协议和 X 协议客户机的端口。

注意

我们将在第八章和第十章中讨论 MySQL 路由器,包括如何设置和使用它。

图 2-17 显示了 MySQL 路由器配置对话框。我们可以使用默认值,所以我们只需要点击完成返回到产品配置对话框(为简洁起见省略–参见图 2-10 )。

img/478423_1_En_2_Fig17_HTML.jpg

图 2-17

MySQL 路由器

在产品配置对话框中,点击下一个的继续。下一个要配置的组件是示例组件。虽然看起来这里没有什么可做的(毕竟,它们只是使用 MySQL 的例子),但是这个对话框有一个非常有趣的特性。该对话框允许您通过连接到服务器来检查服务器安装。这不仅可以测试您的服务器,还可以确保您的安装正常工作。

当对话框出现时,键入您之前选择的 root 密码,然后单击 Check 按钮。这将检查您与服务器的连接(和密码)。

您可能还会注意到,该对话框显示了独立服务器选项和沙箱选项。如果你安装了沙箱选项,你也可以检查运行在沙箱中的 MySQL 服务器。在本演示中,我们仅选中了独立选项。

图 2-18 显示了连接到服务器对话框。

img/478423_1_En_2_Fig18_HTML.jpg

图 2-18

连接到服务器

检查完连接后,点击下一步继续。下一个对话框简单地应用了我们之前看到的配置,但是在本例中,安装程序配置了示例和范例的所有子组件。只需点击执行即可开始。当所有配置完成后,可以点击完成进入下一步。图 2-19 显示了样本和示例的完整配置对话框。

当您点击完成时,您将返回到产品配置对话框,该对话框将显示所有已配置的组件(为简洁起见,此处省略——参见图 2-10 )。点击下一步继续。

img/478423_1_En_2_Fig19_HTML.jpg

图 2-19

样品和示例已完成

所有产品配置完成后,您将看到如图 2-20 所示的安装完成对话框。单击完成退出安装程序。

img/478423_1_En_2_Fig20_HTML.jpg

图 2-20

安装完成

如果您一直在自己的机器上安装 MySQL,那么恭喜您!现在,您已经有了 MySQL Server 和 MySQL Shell 以及完成本书中的示例所需的其他组件。

在 macOS 上安装

在 macOS 上安装 MySQL 产品是通过从 MySQL 网站下载每个产品作为一个单独的包来完成的。例如,如果您想在 macOS 上安装 MySQL Server 和 MySQL Shell,您需要下载它们各自的安装程序。在本节中,我们将看到在 macOS 上安装服务器和 shell 的演练。

我们将先安装 MySQL 服务器,然后安装 MySQL Shell。回想一下,我们必须从 https://dev.mysql.com/downloads/ 为每个下载安装程序。例如,在选择社区服务器条目( https://dev.mysql.com/downloads/mysql/ )并在操作系统下拉列表中选择 macOS 条目后,我们将看到可用于在 macOS 上安装服务器的文件。图 2-21 显示了适用于 MySQL 8.0.16 的文件。

img/478423_1_En_2_Fig21_HTML.jpg

图 2-21

为 macOS 下载 MySQL 服务器

请注意,您将看到几个选项,包括带有引导式安装程序的可挂载磁盘映像(.dmg)以及磁带归档(.tar)。在 macOS 上,您应该使用磁盘映像选项。现在就去下载吧。

类似地,您可以返回到社区下载页面,单击 MySQL Shell 的条目,在操作系统下拉框中选择 macOS 之后,您将看到可用于下载 Shell 安装程序的文件。图 2-22 显示了 MySQL Shell 8.0.16 可用文件的示例。

img/478423_1_En_2_Fig22_HTML.jpg

图 2-22

为 macOS 下载 MySQL Shell

在这里,我们再次看到了一个可挂载的磁盘映像,带有一个引导式安装程序(.dmg)和一个磁带归档文件(.tar)。您应该下载磁盘映像。

现在,让我们看看如何安装服务器。

安装 MySQL 服务器

要安装 MySQL Server,请打开可挂载的磁盘镜像文件(如mysql-8.0.16-macos10.14-x86_64.dmg),然后打开安装程序(如mysql-8.0.16-macos10.14-x86_64.pkg)。这将开始安装。

您将看到的第一个对话框是欢迎对话框,它显示了文档链接列表和步骤的简要总结。对于精明的 macOS 爱好者来说,安装进度会非常熟悉。图 2-23 显示了欢迎对话框。

img/478423_1_En_2_Fig23_HTML.jpg

图 2-23

欢迎对话框

阅读欢迎文本并浏览链接后,点击继续继续。下一个对话框是许可证对话框,您可以选择阅读 GNU 通用公共许可证(GNU GPL)许可证(或者企业许可证,如果您选择下载企业版)。您也可以打印许可证或将许可证保存到文件中,以便以后阅读。图 2-24 显示许可对话框。

img/478423_1_En_2_Fig24_HTML.jpg

图 2-24

许可对话框

点击继续查看许可接受对话框。图 2-25 显示许可协议对话框。同样,您可以阅读许可,但您必须接受许可才能继续。要接受许可证,点击接受

img/478423_1_En_2_Fig25_HTML.jpg

图 2-25

接受许可对话框

接受许可后,您将进入安装类型对话框。请注意,目标选择对话框被跳过。图 2-26 显示安装类型对话框。

img/478423_1_En_2_Fig26_HTML.jpg

图 2-26

安装类型对话框

在此对话框中,您可以选择安装目标。对于大多数系统,您可以接受默认值。如果需要更改目的地,可以点击自定义按钮。要继续安装目的地,点击安装

下一个对话框是进度对话框,显示正在安装的文件的进度。您在这里不会看到太多,所以让我们看看下一个对话框,它开始了配置过程。关闭该对话框后,您将开始配置阶段。图 2-27 显示了配置 MySQL 服务器对话框。

img/478423_1_En_2_Fig27_HTML.jpg

图 2-27

配置 MySQL 服务器(密码)对话框

这里,我们必须选择使用强密码加密(强烈推荐)或使用传统身份验证方法(不推荐用于生产)。默认情况下选择强加密,因此我们只需单击下一个的即可进入下一个配置项。

注意

如果您选择强密码加密方法,并希望使用 MySQL 客户端的旧版本(而不是 shell),您可能会遇到连接错误。您必须使用带有强密码加密的新客户端。

下一个配置项是我们为 root 用户帐户选择密码,如图 2-28 所示。选择一个你能记住并且足够复杂的密码,没有人会轻易猜到。建议您使用由字母、数字和其他字符组合而成的至少八个字符的密码。

我们也可以选择在安装完成后启动 MySQL 服务器。建议在安装后启动服务器,以便您可以检查它是否正常工作。

img/478423_1_En_2_Fig28_HTML.jpg

图 2-28

配置 MySQL 服务器(根用户密码/启动服务器)对话框

输入 root 用户密码并决定是否要启动服务器后,单击 Finish 完成配置并转到 summary 对话框。图 2-29 显示了汇总对话框。

img/478423_1_En_2_Fig29_HTML.jpg

图 2-29

摘要对话框

要完成安装,点击关闭。您可能想要关闭可装载的磁盘映像(如果您不关闭它,它将在关机时关闭)。如果您愿意,现在可以连接到服务器,但是您必须使用旧的客户端。与其这样做,不如让我们安装 Shell。

安装 MySQL Shell

安装 MySQL Shell 与安装服务器非常相似。例外是没有配置步骤。

要安装 MySQL Shell,请打开可挂载的磁盘镜像文件(如mysql-shell-8.0.16-macos10.14-x86-64bit.dmg),然后打开安装程序(如mysql-shell-8.0.16-macos10.14-x86-64bit.pkg)。这将开始安装。

您将看到的第一个对话框是欢迎对话框,它显示了文档链接列表和步骤的简要总结。对于精明的 macOS 爱好者来说,安装进度会非常熟悉。图 2-30 显示了欢迎对话框。

img/478423_1_En_2_Fig30_HTML.jpg

图 2-30

欢迎对话框

阅读欢迎文本并浏览链接后,点击继续继续。下一个对话框是许可证对话框,您可以选择阅读 GPL 许可证(或者企业许可证,如果您选择下载企业版)。您也可以打印许可证或将许可证保存到文件中,以便以后阅读。图 2-31 显示许可对话框。

img/478423_1_En_2_Fig31_HTML.jpg

图 2-31

许可对话框

点击继续查看许可接受对话框。图 2-32 显示许可协议对话框。同样,您可以阅读许可,但您必须接受许可才能继续。要接受许可证,点击接受

img/478423_1_En_2_Fig32_HTML.jpg

图 2-32

接受许可对话框

接受许可后,您将进入安装类型对话框。请注意,目标选择对话框被跳过。图 2-33 显示安装类型对话框。

在此对话框中,您可以选择安装目标。对于大多数系统,您可以接受默认值。如果需要更改目的地,可以点击自定义按钮。要继续安装目的地,点击安装

img/478423_1_En_2_Fig33_HTML.jpg

图 2-33

安装类型对话框

下一个对话框是进度对话框,显示正在安装的文件的进度。这里您不会看到太多,所以让我们看看下一个对话框,它显示了摘要对话框。图 2-34 显示了汇总对话框。

img/478423_1_En_2_Fig34_HTML.jpg

图 2-34

摘要对话框

要完成安装,点击关闭。您可能想要关闭可装载的磁盘映像(如果您不关闭它,它将在关机时关闭)。你现在可以使用 MySQL Shell 连接到服务器,如图 2-35 所示。在这里,我打开了一个终端,输入命令 mysqlsh 来启动 shell。

img/478423_1_En_2_Fig35_HTML.jpg

图 2-35

使用 MySQL Shell (macOS)

如果您一直在自己的机器上安装 MySQL,那么恭喜您!现在,您已经有了 MySQL Server 和 MySQL Shell 以及完成本书中的示例所需的其他组件。

使用 APT 库在 Linux (Ubuntu)上安装

在其他平台上安装 MySQL 服务器和 Shell 最好使用特定于平台的存储库。也就是说,您可以访问 MySQL 下载站点,下载特定于平台的安装程序,并按照 Linux 发行版的通用方法安装 MySQL 产品。

事实上,MySQL 服务器分发包不像其他平台那样是单一下载。这是因为服务器包是以模块化方式构建的。也就是说,您可以分部分安装服务器,包括客户端、公共库、服务器核心等。

然而,Oracle 已经为更流行的 Linux 发行版,特别是 Ubuntu 和 Debian 发行版建立了一种更简单的安装方法。这是通过 APT 存储库实现的,它为您的平台建立了包和引用。例如,一旦你在 Ubuntu 上安装了存储库,你就可以使用 apt 来安装任何你想要的服务器产品,它会自动下载合适的安装程序。

但是 APT 库不仅仅如此。安装后,您可以随时了解 MySQL Server 的最新版本。总的来说,这比每次你想安装新版本的时候手动下载安装程序要容易得多。

在这一节中,我们将看到在 Ubuntu 上使用 MySQL APT 库安装 MySQL 服务器和 MySQL Shell 的演示。让我们从下载和安装存储库开始。

下载 APT 存储库

要下载 APT 资源库,请导航至 MySQL 社区下载页面( https://dev.mysql.com/downloads/ )并点击页面顶部的 APT 资源库菜单项,如图 2-36 所示。

img/478423_1_En_2_Fig36_HTML.jpg

图 2-36

选择 APT 仓库

然后,您将看到 APT 存储库可用的文件。对于 MySQL 8.0.16 版本,只有一个选项,如图 2-37 所示。要下载文件,点击下载

img/478423_1_En_2_Fig37_HTML.jpg

图 2-37

下载 APT 存储库

您可能会被要求登录或注册一个免费的 MySQL 帐户。这是可选的,您可以通过单击“不,谢谢,只需启动按钮下方的我的下载链接”来跳过这一步,如图 2-38 所示。

img/478423_1_En_2_Fig38_HTML.jpg

图 2-38

跳过用于下载 APT 存储库的登录

根据您使用的浏览器,接下来会要求您打开或保存文件。你应该将文件保存在你的Downloads文件夹中或者你能找到的地方,如图 2-39 所示。

img/478423_1_En_2_Fig39_HTML.jpg

图 2-39

保存文件

现在我们已经下载了 APT 存储库,我们可以安装它了。

安装 APT 存储库

要安装 APT 存储库,打开一个终端并切换到保存它的目录(例如,您的Downloads文件夹)。安装 APT 存储库所需的步骤包括:

$ sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
$ sudo apt-get update

第一个命令安装链接 Oracle 存储库所需的软件包源。第二个命令用于更新包源代码并启用新的源代码。清单 2-1 显示了安装 APT 存储库的脚本。你的结果应该差不多。

$ sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
[sudo] password for cbell:
Selecting previously unselected package mysql-apt-config.
(Reading database ... 212217 files and directories currently installed.)
Preparing to unpack mysql-apt-config_0.8.13-1_all.deb ...
Unpacking mysql-apt-config (0.8.13-1) ...
Setting up mysql-apt-config (0.8.13-1) ...
OK
$ sudo apt-get update
Get:1 http://repo.mysql.com/apt/ubuntu xenial InRelease [19.1 kB]
Hit:2 http://us.archive.ubuntu.com/ubuntu xenial InRelease
Get:3 http://security.ubuntu.com/ubuntu xenial-security InRelease [107 kB]
Get:4 http://repo.mysql.com/apt/ubuntu xenial/mysql-8.0 Sources [994 B]
Get:5 http://us.archive.ubuntu.com/ubuntu xenial-updates InRelease [109 kB]
Get:6 http://repo.mysql.com/apt/ubuntu xenial/mysql-apt-config amd64 Packages [567 B]
Get:7 http://repo.mysql.com/apt/ubuntu xenial/mysql-apt-config i386 Packages [567 B]
Get:8 http://repo.mysql.com/apt/ubuntu xenial/mysql-8.0 amd64 Packages [7,150 B]
Get:9 http://repo.mysql.com/apt/ubuntu xenial/mysql-8.0 i386 Packages [7,143 B]
Get:10 http://repo.mysql.com/apt/ubuntu xenial/mysql-tools amd64 Packages [3,353 B]
Get:11 http://repo.mysql.com/apt/ubuntu xenial/mysql-tools i386 Packages [2,632 B]
Get:12 http://us.archive.ubuntu.com/ubuntu xenial-backports InRelease [107 kB]
Fetched 364 kB in 5s (64.6 kB/s)
Reading package lists... Done

Listing 2-1Installing the APT Repository

此时,只需在 APT 命令中指定产品名称,您的系统就可以安装 MySQL 产品了。接下来,让我们安装 MySQL 服务器。

安装 MySQL 服务器

安装带有 APT 存储库的服务器可以通过安装名为 mysql server 的元包来完成。下面显示了可用于安装服务器及其最常用组件(包括客户端)的命令。

$ sudo apt-get install mysql-server

该命令的输出是大多数 Linux 安装的典型输出,并且大多数人对其内容并不感兴趣,因此我们将跳过对输出的检查。如果你很好奇,你可以看到下载和安装的所有包和包的依赖项。

在安装过程中,系统会提示您选择要启用的软件包。大多数情况下,您可以使用默认值。从列表中选择 Ok 条目,继续默认设置。对话框底部的“确定”将转到下一个屏幕,以配置从列表中选择的软件包。图 2-40 显示了允许您配置特定软件包的对话框。如果您想要配置其中一个软件包,使用向上向下箭头键选择该软件包,然后按选项卡键移动到屏幕底部的确定选项以继续。

img/478423_1_En_2_Fig40_HTML.jpg

图 2-40

在 APT 存储库中配置包

您将看到的下一步是选择 root 密码。您应该选择一个容易记住且足够复杂的密码,没有人会轻易猜到。建议您使用由字母、数字和其他字符组合而成的至少八个字符的密码。图 2-41 显示了设置 root 用户密码的对话框。

img/478423_1_En_2_Fig41_HTML.jpg

图 2-41

设置 Root 用户密码

下一个对话框是您在返回终端提示符之前看到的最后一个对话框。您必须选择使用强密码加密(强烈推荐)或使用传统身份验证方法(不推荐用于生产)。默认情况下会选择强加密,所以我们只需使用选项卡键,然后选择 Ok 继续。图 2-42 显示密码加密配置对话框。

注意

如果您选择强密码加密方法,并希望使用 MySQL 客户端的旧版本(而不是 shell),您可能会遇到连接错误。您必须使用带有强密码加密的新客户端。

img/478423_1_En_2_Fig42_HTML.jpg

图 2-42

密码加密对话框

如果一切顺利,你应该被毫不客气地送回终点站。您应该不会看到任何错误,并且可能会看到安装任何附加组件的结果,例如下面的摘录。

...
update-alternatives: using /var/lib/mecab/dic/ipadic-utf8 to provide /var/lib/mecab/dic/debian (mecab-dictionary) in auto mode
Setting up mysql-server (8.0.16-1ubuntu16.04) ...
Processing triggers for libc-bin (2.23-0ubuntu10) ...

接下来,我们用下面的命令启动服务器。请注意,这可能需要一段时间才能在第一次启动时运行,因为服务器必须设置数据目录。

$ sudo service mysql start

现在,您可以连接到服务器。因为我们还没有安装 shell,所以我们可以使用下面的命令来使用旧的客户机。这些选项指定用户(root)和提示输入用户密码的选项。

$ mysql -uroot -p

这将导致启动旧的客户端,看起来非常类似于我们到目前为止看到的 MySQL Shell 的例子。如果你仔细观察,你会发现欢迎声明中的细微差别,但最大的线索是新的提示。清单 2-2 展示了一个使用旧客户端连接到服务器的例子。

$ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.16 MySQL Community Server - GPL

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> \q
Bye!

Listing 2-2Connecting to MySQL (Old Client)

接下来,让我们安装 MySQL Shell,并通过连接到服务器进行测试。

安装 MySQL Shell

要安装 MySQL Shell,我们必须下载 MySQL Shell 分发包。你可以通过访问 https://dev.mysql.com/downloads/shell/ 来做到这一点。然后,您必须更改操作系统以匹配您的系统(如 Ubuntu)和版本(如 18.04),如图 2-43 所示。或者,您可以将版本设置为“All”来查看所有可用的包。点击下载按钮,下载与您的系统相匹配的软件包。

img/478423_1_En_2_Fig43_HTML.jpg

图 2-43

下载 MySQL Shell (Ubuntu)

例如,我使用的是运行 64 位版本的 Ubuntu 18.04。因此,我下载了名为 mysql-shell _ 8 . 0 . 16-1 Ubuntu 18.04 _ amd64 . deb 的文件。回想一下,根据您使用的浏览器,您可能需要点击 MySQL 下载接受对话框(见图 2-38 )并保存文件(见图 2-39 )。下载完成后,您可以使用以下命令安装 shell。

$ sudo dpkg -i ./mysql-shell_8.0.16-1ubuntu18.04_amd64.deb

运行该命令的输出非常短,如下所示。

(Reading database ... 151363 files and directories currently installed.)
Preparing to unpack .../mysql-shell_8.0.16-1ubuntu18.04_amd64.deb ...
Unpacking mysql-shell:amd64 (8.0.16-1ubuntu18.04) ...
Setting up mysql-shell:amd64 (8.0.16-1ubuntu18.04) ...

您还可以通过使用以下命令,使用 APT 存储库安装 shell。无论您使用哪一种都可以,但是使用 APT 存储库是首选的方法。

$ sudo apt-get install mysql-shell

至此,我们已经安装并配置了 MySQL 服务器和 Shell。现在,让我们通过在终端窗口中发出以下命令来测试这两者。

$ mysqlsh

一旦输入该命令,您将看到 shell 启动,如图 2-44 所示。

img/478423_1_En_2_Fig44_HTML.jpg

图 2-44

使用 MySQL Shell (Ubuntu)

注意,在这个例子中,我发出了几个命令。以斜杠(\)开头的命令是 shell 命令。首先是将模式改为 SQL ( \sql)用于处理 SQL 命令,然后我使用\connect命令连接到服务器,将用户 id、主机和端口作为root@localhost:3306传递。最后,我发出一个 SQL 命令来显示所有的数据库。我们将在下一章学习更多关于使用 shell 的知识。

如果您一直在自己的机器上安装 MySQL,那么恭喜您!现在,您已经有了 MySQL Server 和 MySQL Shell 以及完成本书中的示例所需的其他组件。

摘要

对于 MySQL 客户端来说,MySQL Shell 是技术上的一次巨大飞跃。它不仅被设计为以更智能的方式与 MySQL 中的 SQL 一起工作,还被设计为支持 JavaScript 和 Python 的原型。您可以使用任何您想要的语言,并在它们之间轻松切换,而不必重新启动应用或断开连接。多酷啊。

在本章中,我们学习了如何安装 MySQL Shell。我们还学习了如何安装 MySQL 服务器。演示了使用 MySQL 安装程序在 Windows 上安装 MySQL,使用 APT 库在 macOS 和 Linux (Ubuntu)上安装 MySQL。

在下一章中,我们将看到一个关于 shell 及其主要特性的简短教程。

三、MySQL Shell 教程

既然我们已经知道了 MySQL Shell 是什么以及它在 MySQL 产品套件中的位置,那么是时候了解 Shell 能为我们做什么了。具体来说,它支持哪些命令,如何连接服务器,支持哪些功能?

在这一章中,我们将更详细地探讨 MySQL Shell。我们将了解更多关于它的主要特性和选项,以及如何使用新的 shell 来交互式地执行脚本。正如您将看到的,MySQL Shell 是 MySQL 未来的一个重要元素。让我们从 shell 支持的命令和选项开始。

命令和选项

如果您认为新的 shell 只不过是原始客户端的改进版本,那么您就大错特错了。shell 不仅仅是原始客户端的简单替换。为了让您开始了解它的不同之处,以及它如何比原来的 shell 复杂得多,让我们从检查支持的命令和选项开始。

命令是您可以在提示符下提供的特殊条目,它直接与 MySQL Shell 应用交互。这些命令通常被称为 shell 命令,并以斜杠(\)开头。选项指的是启动 MySQL Shell 时可以指定的许多参数(选项)。因此,shell 支持启动时的定制,比如连接到服务器、设置模式等等。

在接下来的几节中,我们将了解更多关于 shell 的命令和选项,但是首先让我们简单地讨论一下如何启动 shell。

启动 MySQL Shell

根据您的平台和安装 shell 的方式,您可以从系统(例如,开始)菜单启动 shell。但是,在所有平台上,安装都将 shell 可执行文件放在可以从命令行执行的地方。Windows 上的 shell 可执行文件命名为mysqlsh.exe。在其他平台上,简直就是mysqlsh

例如,在 Windows 上,您可以在特殊的终端中使用开始菜单启动 shell,如图 3-1 所示。

img/478423_1_En_3_Fig1_HTML.jpg

图 3-1

从“开始”菜单启动 Shell(Windows)

大多数人会从命令行启动 shell。我们可以通过打开终端(或控制台)并运行 shell 可执行文件来实现这一点。例如,图 3-2 显示了如何从命令窗口启动 Windows 上的 shell。你可以在其他平台上做同样的事情。

img/478423_1_En_3_Fig2_HTML.jpg

图 3-2

从命令行启动 Shell(Windows)

命令

像最初的 MySQL 客户端一样,有一些特殊的命令控制应用本身,而不是与数据交互(通过 SQL 或 X DevAPI)。要执行 shell 命令,请发出带斜线(\)的命令。例如,\help打印所有 shell 命令的帮助。表 3-1 列出了一些更常用的 Shell 命令。

表 3-1

Shell 命令

|

命令

|

捷径

|

描述

| | --- | --- | --- | | \ |   | 开始多行输入(仅限 SQL 模式) | | \connect | \c | 连接到服务器 | | \help | \?,\h | 打印帮助文本 | | \history |   | 查看和编辑命令行历史 | | \js |   | 切换到 JavaScript 模式 | | \nowarnings | \w | 不显示警告 | | \option |   | 查询和更改 MySQL Shell 配置选项 | | \py |   | 切换到 Python 模式 | | \quit | \q,\exit | 放弃 | | \reconnect |   | 重新连接到同一个 MySQL 服务器 | | \rehash |   | 手动更新自动完成名称缓存 | | \source | \. | 执行指定的脚本文件 | | \sql |   | 切换到 SQL 模式 | | \status | \s | 打印有关连接的信息 | | \use | \u | 设置会话的模式 | | \warnings | \W | 在每个语句后显示警告 |

有些命令,如\connect 命令,带有一个或多个参数。学习如何使用 shell 命令的最好方法是使用\help命令。您可以使用不带参数的命令来获得相关帮助。例如,要了解更多关于\connect命令的信息,输入\help connect,如清单 3-1 所示。这里,我们从命令行启动 shell,不带任何选项,它以默认的 JavaScript 模式启动,发出几个 help 命令,然后用\q命令退出 shell。为了简洁起见,省略了部分输出,命令以粗体显示,以便于阅读。

C:\>mysqlsh

MySQL Shell 8.0.16
...
 MySQL  JS > \help sql
Found several entries matching sql

The following topics were found at the X DevAPI category:

- mysqlx.Session.sql
- mysqlx.SqlExecute.sql

For help on a specific topic use: \? <topic>

e.g.: \? mysqlx.Session.sql

 MySQL  JS > \help connect
NAME
      connect - Establishes the shell global session.

SYNTAX
      shell.connect(connectionData[, password])

WHERE
      connectionData: the connection data to be used to establish the session.
      password: The password to be used when establishing the session.

DESCRIPTION
      This function will establish the global session with the received
      connection data.

      The connection data may be specified in the following formats:

      - A URI string
      - A dictionary with the connection options
...
 MySQL  JS > \q
Bye!

Listing 3-1Getting Help in MySQL Shell

小费

使用\help <command>了解如何使用新命令。

您可以使用\sql\js\py shell 命令动态切换模式。这不仅意味着您可以在不重启 shell 的情况下更改模式,还允许您随时切换模式,从而使处理 SQL 和 NoSQL 数据变得更加容易。例如,您可以执行一些 SQL 命令,然后连接到 X DevAPI 来运行 JavaScript,返回到 SQL,然后切换到运行 Python 脚本。此外,即使使用了启动选项来设置模式,也可以使用这些 shell 命令。

注意,退出 shell 的方式是使用\q(或\quit)命令。如果您像在旧客户端中习惯的那样键入quit,shell 将根据您所处的模式做出不同的响应。清单 3-2 展示了每种模式下发生的情况。让我们从默认模式(JavaScript)开始,然后切换到 Python,最后是 SQL 模式。

MySQL  JS > quit
ReferenceError: quit is not defined

 MySQL  JS > \py
Switching to Python mode...

 MySQL  Py > quit
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'quit' is not defined

 MySQL  Py > \sql
Switching to SQL mode... Commands end with ;

 MySQL  SQL > quit;
ERROR: Not connected.

 MySQL  SQL >
 MySQL  SQL > \quit
Bye!

Listing 3-2Results of Using quit in Different Modes

如果您习惯了旧的 MySQL 客户端,并且不小心使用了旧的客户端命令,您可能会看到类似的奇怪现象,但是只需要经常使用它就可以提醒您要使用的正确命令。现在,让我们看看 shell 的命令行选项。

选择

可以使用几个控制模式、连接、行为等的启动选项来启动 shell。本节介绍一些您可能想要使用的更常用的选项。我们将在后面的章节中看到更多关于连接选项的内容。表 3-2 显示了常见的 Shell 选项。这些只是众多选择中的几个。

表 3-2

常见的 MySQL Shell 选项

|

[计]选项

|

描述

| | --- | --- | | --auth-method=method | 要使用的身份验证方法 | | --cluster | 确保目标是 InnoDB 集群的一部分 | | --compress | 启用客户端和服务器之间的压缩 | | --database=name | - schema 的别名 | | --dba=enableXProtocol | 在连接到的服务器中启用 X 协议。必须与- mysql 一起使用 | | --dbpassword=name | 连接到服务器时使用的密码 | | --dbuser=name, -u | 用于连接的用户 | | --execute=<cmd>, -e | 执行命令并退出 | | --file=file, -f | 用于执行的流程文件 | | --host=name, -h | 用于连接的主机名 | | --import | 导入一个或多个 JSON 文档 | | --interactive[=full], -i | 为了在批处理模式下使用,它强制模拟交互模式处理。批处理中的每一行都像在交互模式下一样进行处理 | | --js | 以 JavaScript 模式启动 | | --json=[raw&#124;pretty] | 以 raw 格式(无格式)或 pretty(人类可读格式)生成 JSON 格式的输出 | | --log-level=value | 日志级别。值必须是 1 到 8 之间的整数或[无、内部、错误、警告、信息、调试、调试 2、调试 3]中的任何一个 | | --mc --mysql | 创建经典(旧协议)会话 | | --mx --mysqlx | 创建一个 X 协议会话(简称为“会话”) | | --name-cache | 为默认模式启用表名加载 | | --no-name-cache | 禁止加载默认模式的表名 | | --nw, --no-wizard | 禁用执行脚本的向导模式(非交互式) | | -p | 请求密码提示以设置密码 | | --password=name | dbpassword 的别名 | | --port=#, -P | 用于连接的端口号 | | --py | 以 Python 模式启动 | | --schema=name, -D | 要使用的架构 | | --socket=sock, -S | UNIX 中用于连接的套接字名称或 Windows 中的命名管道名称(仅限经典会话) | | --sql | 以 SQL 模式启动 | | --sqlc | 使用经典会话在 SQL 模式下启动 | | --sqlx | 使用创建 X 协议会话在 SQL 模式下启动 | | --ssl-ca=name | PEM 格式的 CA 文件(查看 OpenSSL 文档) | | --ssl-capath=dir | CA 目录 | | --ssl-cert=name | PEM 格式的 X509 证书 | | --ssl-cipher=name | 要使用的 SSL 密码 | | --ssl-crl=name | 证书吊销列表 | | --table | 以表格格式显示结果 | | --tabbed | 以选项卡格式显示结果 | | --uri | 以user@host:port的形式提供连接信息 | | --vertical | 以垂直格式显示结果(如\G) |

请注意,有些选项有别名,其用途与原始客户端相同。如果您有启动客户机来执行操作的脚本,这使得切换到 shell 变得更容易一些。还要注意,有一组使用安全套接字层(SSL)连接的选项。还有一些选项可以控制输出的显示方式——传统的表格(比如 SQL 结果)、垂直方向,甚至是 JSON。花点时间浏览一下这个列表,让自己熟悉哪些是可用的。但是,还有其他不常用的选项。有关可用选项的完整列表,请参见 https://dev.mysql.com/doc/mysql-shell/8.0/en/mysqlsh.html 。现在不要担心记住它们或如何使用它们——我们将在后面的章节中看到它们的实际应用。

MySQL Shell 入门

正如我们所了解的,MySQL Shell 是 MySQL 产品组合中一个令人兴奋的新成员。它不仅是一个新的客户端,还是一个优秀的脚本环境,可以用来开发处理数据的新工具和应用。酷!

注意

我们不会检查 MySQL Shell 的每个方面;相反,我们专注于常用的特性。我们还将在后面的章节中看到许多演示的特性。有关应用日志、启动脚本和使用环境变量( https://dev.mysql.com/doc/mysql-shell/8.0/en/ )等附加功能的更多信息,请参见 MySQL Shell online 用户手册。

让我们再看一次壳牌的行动。清单 3-3 展示了一个使用命令行选项通过统一资源标识符(URI)连接到我们的 MySQL 服务器的例子,设置默认模式,模式为 SQL,输出格式为 vertical。

注意

在以后的例子中,我将使用清单而不是图形来展示运行中的 shell。

C:\Users\cbell>mysqlsh --sql --uri=root@localhost -p -D world --vertical
Creating a session to 'root@localhost/world'
Please provide the password for 'root@localhost': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost'? [Y]es/[N]o/Ne[v]er (default No):
Fetching schema names for autocompletion... Press ^C to stop.
Fetching table and column names from `world` for auto-completion... Press ^C to stop.
Your MySQL connection id is 11 (X protocol)
Server version: 8.0.16 MySQL Community Server - GPL
Default schema set to `world`.
MySQL Shell 8.0.16

Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type '\help' or '\?' for help; '\quit' to exit.

 MySQL  localhost:33060+ ssl  world  SQL > SHOW TABLES;
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Tables_in_world: city
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Tables_in_world: country
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 3\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
Tables_in_world: countrylanguage
3 rows in set (0.0014 sec)

 MySQL  localhost:33060+ ssl  world  SQL > \q
Bye!

Listing 3-3Starting the MySQL Shell with Options

正如您所看到的,您可以使用或不使用选项来启动 shell。您可以选择在启动时连接,或者在启动 shell 后等待并连接到服务器。事实上,无论是否使用命令行选项进行连接,都可以在不重新启动应用的情况下更改到另一台服务器的连接。当使用多个 MySQL 服务器时,这是一个很好的特性,正如我们将看到的,这也是有效设置高可用性解决方案的关键。

正如我们在表格和前面的例子中看到的,您必须使用\connect shell 命令来连接服务器。这些连接称为会话,shell 有几个处理会话的特性。连接可以使用原始的客户机/服务器协议,也可以使用新的 X 协议,通过 X 插件与服务器通信。这意味着 shell 允许您处理关系文档(SQL)和/或 JSON 文档(NoSQL)。我们将在后面的章节中发现更多关于连接的内容。

除了会话,理解 shell 支持的各种模式也很重要。回想一下,这些包括 SQL、JavaScript 和 Python 模式。像连接一样,您可以在命令行上指定模式,并在使用 shell 时随时更改模式。这使您可以根据需要在 Python 和 SQL 之间来回切换,而无需离开应用。

以下部分从较高的层次上介绍了 shell 的会话和模式功能。了解这些特性是理解如何在 shell 中建立连接的关键。我们将在后面的章节中继续学习如何建立连接。有关 MySQL Shell 的更多信息,请参见在线 MySQL 参考手册中标题为“MySQL Shell 用户指南”的部分。

会话和模式

像最初的客户端和大多数 MySQL 客户端应用一样,您需要连接到 MySQL 服务器,以便运行命令。MySQL Shell 支持多种连接 MySQL 服务器的方式和多种与服务器交互的选项(称为会话)。在会话中,您可以更改 shell 接受命令的方式(称为模式),以包括 SQL、JavaScript 或 Python 命令。

考虑到使用服务器的所有不同的新概念,那些初学使用 shell 的人可能会发现其中的细微差别,甚至有时会感到困惑。事实上,在线参考手册和各种博客以及其他报告有时会互换使用模式和会话,但是正如您将看到的,它们是不同的(无论多么微妙)。让我们从查看可用的会话对象开始。

会话对象

关于会话,首先要理解的是,会话是到单个服务器的连接。第二件要理解的事情是,每个会话可以使用两个会话对象中的一个来启动,这两个会话对象公开了一个特定的对象,用于使用特定的通信协议与 MySQL 服务器一起工作。也就是说,会话是到服务器的连接(定义了所有参数),会话对象是 shell 用来以几种方式之一与服务器进行交互的对象。更具体地说,MySQL Shell 会话对象简单地定义了如何与服务器交互,包括支持什么模式,甚至 Shell 如何与服务器通信。shell 支持如下两个会话对象:

  • 会话:X 协议会话用于应用开发,支持 JavaScript、Python、SQL 模式。通常用于开发脚本或执行脚本。要使用该选项启动 shell,请使用--mx ( --mysqlx)选项。

  • 经典会话:使用旧的服务器通信协议,对 DevAPI 的支持非常有限。对没有 X 插件或不支持 X 协议的旧服务器使用这种模式。通常用于旧服务器的 SQL 模式。要使用该选项启动 shell,请使用--mc ( --mysqlc)选项。

通过为经典会话指定-mc或为 X 协议会话指定-mx,可以指定使用\connect shell 命令时要使用的会话对象(协议)。下面依次展示了其中的每一个。注意<URI>指定了统一资源标识符。

  • \connect -mx <URI>:使用 X 协议(会话)

  • \connect -mc <URI>:使用经典协议(经典会话)

本章和其他地方提到的 URI 是指连接到 MySQL 服务器时使用的连接信息的特定格式或布局。下面显示了构建 URI 的格式。

[scheme://][user[:[password]]@]target[:port][/schema][?attribute1=value1&attribute2=value2...

注意,我们可以指定可选的连接(会话)类型、用户、密码(不推荐)、目标或主机、端口,甚至模式以及会话类型使用的任何选项。例如,用于连接到本地 MySQL 服务器的简单 URI 如下所示。这里,我们使用用户名 root 和端口 3306。如果 URI 中没有密码,shell 将提示输入密码。

/connect root@localhost:3306

当然,您仍然可以对用户、主机和端口使用单独的命令行选项。然而,标准做法是将 URIs 与/connect命令或命令行选项一起使用。

小费

有关使用 URIs 的更多信息,请参见 https://dev.mysql.com/doc/refman/8.0/en/connecting-using-uri-or-key-value-pairs.html

召回会话大致等同于连接。但是,会话不仅仅是一个连接,因为它包含了用于建立连接的所有设置(包括会话对象)以及用于与服务器通信的协议。因此,我们有时会遇到术语“协议”来描述会话。

支持的模式

shell 支持三种模式(也称为语言支持或简称为活动语言);SQL、JavaScript 和 Python。回想一下,我们可以使用 shell 命令启动这些模式中的任何一种。你可以随时切换模式(语言),每次都不会断线。下面列出了三种模式以及如何切换到每种模式。

  • \sql:切换到 SQL 语言

  • \js:切换到 JavaScript 语言(默认模式)

  • \py:切换到 Python 语言

您可以随时切换模式,也可以在特定模式下启动 shell。默认模式是 JavaScript。因此,如果您没有在命令行上指定模式,您将会看到 JavaScript 提示。这是你知道自己处于哪种模式的方法。图 3-3 显示了各种模式。它们还用 JavaScript 黄色、SQL 橙色和 Python 蓝色进行了颜色编码。不错!

img/478423_1_En_3_Fig3_HTML.jpg

图 3-3

MySQL Shell 模式提示

现在我们已经了解了会话和模式,我们可以看看如何连接到 MySQL 服务器。

使用连接

在 shell 中建立连接可能需要一些时间来适应与最初的 MySQL 客户端不同的工作方式,最初的 MySQL 客户端需要在命令行中使用几个选项。您可以使用特殊格式的 URI 字符串,或者通过名称使用单个选项连接到服务器(像旧客户端一样)。也支持 SSL 连接。可以通过启动选项、shell 命令和脚本来建立连接。但是,所有连接都需要使用密码。因此,除非您另外声明,否则如果没有给出密码,shell 将提示您输入密码。

注意

如果您想使用没有密码的连接(不推荐),您必须使用--password选项,或者,如果使用 URI,包括一个额外的冒号来代替密码。

下面不是讨论所有可用的连接方式和选项,而是在下面的部分中给出每种连接方式的一个示例。

使用 URI

回想一下,URI 是一个使用特殊格式来包含各种参数值的字符串。密码、端口和模式是可选的,但用户和主机是必需的。在这种情况下,模式是连接时要使用的默认模式(数据库)。旧客户机/服务器协议的默认端口是 3306,X 协议的默认端口是 33060。要在启动 shell 时使用命令行上的 URI 连接到服务器,请使用--uri选项指定如下。

$ mysqlsh --uri root:secret@localhost:3306

小费

如果您省略了--uri但仍然包含一个 URI,那么 shell 将处理作为 URI 出现的字符串。

shell 假定所有连接都需要密码,如果没有提供密码,它将提示输入密码。清单 3-4 显示了前面没有密码的连接。注意 shell 是如何提示输入密码的。

C:\Users\cbell>mysqlsh --uri root@localhost:33060/world_x --sql
Creating a session to 'root@localhost:33060/world_x'
Please provide the password for 'root@localhost:33060': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:33060'? [Y]es/[N]o/Ne[v]er (default No):
Fetching schema names for autocompletion... Press ^C to stop.
Fetching table and column names from `world_x` for auto-completion... Press ^C to stop.
Your MySQL connection id is 16 (X protocol)
Server version: 8.0.16 MySQL Community Server - GPL
Default schema set to `world_x`.
MySQL Shell 8.0.16

Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type '\help' or '\?' for help; '\quit' to exit.

 MySQL  localhost:33060+ ssl  world_x  SQL > \q
Bye!

Listing 3-4Connecting with a URI

注意,我们还用 URI 中的模式选项指定了默认模式( world_x )。 world_x 数据库是一个示例数据库,您可以从 https://dev.mysql.com/doc/index-other.html 下载。我们将在后面的 MySQL Shell 教程中安装这个数据库。

使用单个选项

您还可以使用单独的选项在 shell 命令行上指定连接。可用的连接选项如表 3-1 所示。清单 3-5 展示了如何使用单独的选项连接到 MySQL 服务器。注意,我用--py选项将模式(语言)改为 Python。

C:\Users\cbell>mysqlsh --user root --host localhost --port 33060 --schema world_x --py --mx
Creating an X protocol session to 'root@localhost:33060/world_x'
Please provide the password for 'root@localhost:33060': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:33060'? [Y]es/[N]o/Ne[v]er (default No):
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 17 (X protocol)
Server version: 8.0.16 MySQL Community Server - GPL
Default schema `world_x` accessible through db.
MySQL Shell 8.0.16

Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type '\help' or '\?' for help; '\quit' to exit.

 MySQL  localhost:33060+ ssl  world_x  Py > \q

Bye!

Listing 3-5Connecting Using Individual Options

在脚本中使用连接

如果您计划使用 shell 来创建脚本或者仅仅作为一个原型工具,那么您还会希望在脚本中使用会话。虽然有些例子可能看起来很奇怪,并且没有详细的解释,但是在学习如何执行这些步骤的细节(以及为什么)之前,看看事情是如何进行的总是一个好主意。因此,您应该阅读这一部分,以熟悉什么是可能的。在本节中,我们将探讨如何在脚本中使用会话。我们将在后面的章节中学习如何使用这些例子。

在脚本中使用会话的强大之处在于我们可以保存它们并在以后重用它们。在这种情况下,我们将创建一个变量来包含获取的会话。以这种方式创建的会话称为全局会话,因为一旦创建,它就可用于任何模式。然而,根据我们使用的会话对象(回想一下这是经典还是 X 协议),我们将使用不同的方法创建一个 X 或经典会话。我们对 X 协议会话对象使用get_session()方法,对经典会话对象使用get_classic_session()方法。

注意

我们将把重点放在 Python 脚本上,但是许多例子也适用于 JavaScript,尽管类和方法的大小写略有不同。

下面演示如何在 Python 中获取 X 协议会话对象。注意,我在 URI 中指定了密码,并将密码作为单独的参数。为了简洁起见,我省略了 shell 提示符。

> my_session = mysqlx.get_session('root@localhost:33060', 'secret');
> print(my_session)
<Session:root@localhost:33060>

以下演示了如何在 Python 中获取经典会话对象。

Py > my_classic = mysql.get_classic_session('root@localhost:3306', 'secret');
Py > print(my_classic)
<ClassicSession:root@localhost:3306>

使用 SSL 连接

您还可以创建 SSL 连接,以便安全地连接到您的服务器。要使用 SSL,您必须将服务器配置为使用 SSL。要在运行 MySQL 的同一台机器上使用 SSL,可以使用--ssl-mode=REQUIRED选项。

使用 SHOW VARIABLES 命令查看 SSL 变量的状态,以确定您的服务器是否启用了 SSL。清单 3-6 显示了使用%包围的 ssl 运行查询的结果,这是通配符。这将导致显示名称中带有 ssl 的所有变量。我们可以看到,SSL 确实是启用的(见have_ssl,显示的是YES)。如果您的服务器没有设置为使用 SSL,而您想要使用 SSL 连接,请参阅在线 MySQL 参考手册( https://dev.mysql.com/doc/refman/8.0/en/encrypted-connections.html )以了解如何在您的服务器上设置 SSL。

SQL > SHOW VARIABLES LIKE '%ssl%';
+--------------------+-----------------+
| Variable_name      | Value           |
+--------------------+-----------------+
| have_openssl       | YES             |
| have_ssl           | YES             |
| mysqlx_ssl_ca      |                 |
| mysqlx_ssl_capath  |                 |
| mysqlx_ssl_cert    |                 |
| mysqlx_ssl_cipher  |                 |
| mysqlx_ssl_crl     |                 |
| mysqlx_ssl_crlpath |                 |
| mysqlx_ssl_key     |                 |
| ssl_ca             | ca.pem          |
| ssl_capath         |                 |
| ssl_cert           | server-cert.pem |
| ssl_cipher         |                 |
| ssl_crl            |                 |
| ssl_crlpath        |                 |
| ssl_fips_mode      | OFF             |
| ssl_key            | server-key.pem  |
+--------------------+-----------------+
17 rows in set (0.0207 sec)

Listing 3-6Checking for SSL Support

您也可以指定 SSL 选项,如表 3-1 所示。您可以使用命令行选项在命令行上指定它们,或者将其作为\connect shell 命令的扩展。下面显示了如何使用 SSL 和命令行选项连接到服务器。

C:\Users\cbell>mysqlsh -uroot -h127.0.0.1 --port=33060 --ssl-mode=REQUIRED

注意

MySQL 服务器的旧版本可能没有启用 X 插件。请参阅在线 MySQL 参考手册,了解如何在版本 5.7 和 8.0 的早期版本中启用 X 插件。

现在,让我们通过演示 MySQL Shell 的基本特性来看看它的运行情况。

使用 MySQL Shell

以下部分演示了如何在最基本的操作中使用 MySQL shell 选择和插入数据。这些示例使用了 world_x 数据库,旨在提供一个概述,而不是深入探讨。如果您对 MySQL 文档存储或 JSON 数据一无所知,不要绝望;本教程旨在演示如何使用 MySQL Shell,因为该 Shell 旨在用于 JSON 文档,所以我们将这样做。

因此,本教程的目标是在 world_x 数据库中插入新数据,然后执行搜索以检索满足包含新数据的条件的行。我将使用关系表来说明这些概念,因为对于我们这些熟悉“普通”数据库操作的人来说,这更容易理解。

在开始我们的旅程之前,让我们花点时间安装我们将需要的示例数据库,Oracle 的示例 MySQL 数据库。

安装示例数据库

Oracle 提供了几个示例数据库,供您在测试和开发应用时使用。样本数据库可以从 http://dev.mysql.com/doc/index-other.html 下载。我们想要使用的示例数据库被命名为 world_x ,以表明它包含 JSON 文档,并且打算用 X DevAPI、shell 等进行测试。继续前进,导航到该页面并下载数据库。示例数据库包含几个关系表(countrycitycountrylanguage)以及一个集合(countryinfo)。

下载完文件后,解压缩并记下文件的位置。我们进口的时候你会需要的。接下来,启动 MySQL Shell 并连接到您的服务器。使用\sql shell 命令切换到 SQL 模式,然后使用\source shell 命令读取world_x.sql文件并处理其所有语句。清单 3-7 展示了如何使用这些选项并安装示例数据库。为简洁起见,省略了运行\source 命令的响应。

JS > \sql
Switching to SQL mode... Commands end with ;
SQL > \source world_x.sql
Query OK, 0 rows affected (0.0034 sec)
Query OK, 0 rows affected (0.0004 sec)
Query OK, 0 rows affected (0.0003 sec)
…
Query OK, 0 rows affected (0.0003 sec)
Query OK, 0 rows affected (0.0002 sec)
Query OK, 0 rows affected (0.0003 sec)
Query OK, 0 rows affected (0.0003 sec)
Query OK, 0 rows affected (0.0002 sec)
Query OK, 0 rows affected (0.0003 sec)

 MySQL  localhost:3306 ssl  SQL > show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sakila             |
| sys                |
| world_x            |
+--------------------+
6 rows in set (0.0045 sec)
SQL > USE world_x;
Query OK, 0 rows affected (0.00 sec)
SQL > SHOW TABLES;
+-------------------+
| Tables_in_world_x |
+-------------------+
| city      |
| country   |
| countryinfo       |
| countrylanguage   |
+-------------------+
4 rows in set (0.00 sec)

Listing 3-7Installing the world_x Sample Database

注意,我安装了另一个名为 sakila 的示例数据库,您也可以在 Oracle 网站上找到这个数据库和 world_x 数据库。我还展示了位于示例数据库中的表。

小费

如果文件的路径中有空格,应该用双引号将路径括起来。

您还可以使用命令行上的--recreate-schema选项安装示例数据库,如下所示。请注意,如果数据库已经存在,这将删除并重新创建数据库。这是批处理运行 SQL 命令的另一个例子。

C:\Users\cbell\Downloads\world_x-db>mysqlsh -uroot -hlocalhost --sql --recreate-schema --schema=world_x < world_x.sql
Please provide the password for 'root@localhost': ∗∗∗∗∗∗∗∗∗∗

Please pick an option out of [Y]es/[N]o/Ne[v]er (default No):
Recreating schema world_x...

当然,您可以使用 similar source 命令在旧客户机上安装 sample 数据库,但是这有什么意思呢?

现在,让我们看看如何处理数据。

使用数据

在本节中,我们将看到一些在数据库中选择和插入数据的简单示例。我使用 world_x 数据库中的城市表来演示查询中的 JSON 数据类型。正如您将看到的,这开启了一种处理数据的新方式。同样,我们将在下一章看到更多关于 JSON 数据类型的内容。对于这一节,您应该关注 shell 中的交互。也就是说,如何使用 shell 来运行查询。如果您是 SQL 数据库专家,那么除了 JSON 数据类型之外,所有这些都非常熟悉。先说查询数据。

我们要完成的任务是查看城市表中有哪些行。在这种情况下,我们将检索(选择)那些包含美国城市的行。我们将按名称对行进行排序,为了简洁起见,只显示前 20 行。清单 3-8 展示了如何执行查询。即使你不懂 SQL,这个查询读起来也很容易。

SQL > SELECT Name, District, Info FROM city WHERE CountryCode = 'USA' ORDER BY Name DESC LIMIT 20;
+------------------+----------------------+------------------------+
| Name             | District             | Info                   |
+------------------+----------------------+------------------------+
| Yonkers          | New York             | {"Population": 196086} |
| Worcester        | Massachusetts        | {"Population": 172648} |
| Winston-Salem    | North Carolina       | {"Population": 185776} |
| Wichita Falls    | Texas                | {"Population": 104197} |
| Wichita          | Kansas               | {"Population": 344284} |
| Westminster      | Colorado             | {"Population": 100940} |
| West Valley City | Utah                 | {"Population": 108896} |
| West Covina      | California           | {"Population": 105080} |
| Waterbury        | Connecticut          | {"Population": 107271} |
| Washington       | District of Columbia | {"Population": 572059} |
| Warren           | Michigan             | {"Population": 138247} |
| Waco             | Texas                | {"Population": 113726} |
| Visalia          | California           | {"Population": 91762}  |
| Virginia Beach   | Virginia             | {"Population": 425257} |
| Vancouver        | Washington           | {"Population": 143560} |
| Vallejo          | California           | {"Population": 116760} |
| Tulsa            | Oklahoma             | {"Population": 393049} |
| Tucson           | Arizona              | {"Population": 486699} |
| Torrance         | California           | {"Population": 137946} |
| Topeka           | Kansas               | {"Population": 122377} |
+------------------+----------------------+------------------------+
20 rows in set (0.0024 sec)

Listing 3-8
Selecting Rows

注意Info栏。这是一个 JSON 数据类型列,数据显示为 JSON 文档(例如,{"Population": 122377})。这表明 JSON 文档包含一个表示每个城市人口的键/值对。我们可以看到这个表是如何使用清单 3-9 中所示的SHOW CREATE TABLE查询构建的。这里,我们看到了Info列的 JSON 数据类型。

SQL > SHOW CREATE TABLE city\G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
       Table: city
Create Table: CREATE TABLE `city` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `Name` char(35) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `CountryCode` char(3) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `District` char(20) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
  `Info` json DEFAULT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=utf8
1 row in set (0.0038 sec)

Listing 3-9SHOW CREATE TABLE Example

您可能想知道我们是否可以在查询中的Info列中使用 JSON 文档。答案是,可以,可以!我们可以使用一个特殊的函数(为处理 JSON 数据类型而设计的几十个函数之一)来提取键、值对。在这种情况下,我们将使用JSON_EXTACT()函数传入列名和一个称为路径表达式的特殊格式的字符串。在这种情况下,我们希望选择那些代表人口超过 500,000 的城市的行。清单 3-10 显示了修改后的查询的一个例子。在这种情况下,我们将输出限制为前 10 行,但保留排序选项,并将列限制为 name、district 和 information 列。此外,我们将以批处理模式使用 shell 来启动 shell,运行查询,然后退出。

C:\Users\cbell\Downloads\world_x-db>mysqlsh --uri=root@localhost:3306 --sql --table -e "SELECT Name, District, Info FROM world_x.city WHERE CountryCode = 'USA' AND JSON_EXTRACT(Info, '$.Population') > 500000 ORDER BY Name DESC LIMIT 10;"
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):
+---------------+----------------------+-------------------------+
| Name          | District             | Info                    |
+---------------+----------------------+-------------------------+
| Washington    | District of Columbia | {"Population": 572059}  |
| Seattle       | Washington           | {"Population": 563374}  |
| San Jose      | California           | {"Population": 894943}  |
| San Francisco | California           | {"Population": 776733}  |
| San Diego     | California           | {"Population": 1223400} |
| San Antonio   | Texas                | {"Population": 1144646} |
| Portland      | Oregon               | {"Population": 529121}  |
| Phoenix       | Arizona              | {"Population": 1321045} |
| Philadelphia  | Pennsylvania         | {"Population": 1517550} |
| Oklahoma City | Oklahoma             | {"Population": 506132}  |
+---------------+----------------------+-------------------------+

Listing 3-10Selecting Rows Using JSON Data Type (Batch Mode)

让我们更仔细地看看这个命令。注意,我们用--uri启动 shell 以提供登录信息,--sql启动 SQL 模式,--table以表格模式显示输出(默认为 tab),而-e选项后跟执行并返回结果的查询。您可以使用这种机制在任何批处理作业中插入 shell。

我们要做的下一个任务是插入数据。为了让事情变得有趣,我们将修改一些行,以包含您在镇上可以访问的有趣网站。在纯关系数据库中,这需要更改表或添加新表来存储新信息。但是 JSON 数据类型允许我们通过更多的键、值对以自由形式添加信息。因此,我们将修改信息列,以包括关于感兴趣的站点的附加信息。换句话说,我们可以添加自己对去过的地方的评论,并推荐给其他人。

对于这个例子,我们将添加两个站点;华盛顿特区的史密森尼国家航空航天博物馆( https://airandspace.si.edu/ )和马里兰州的国家海港( https://www.nationalharbor.com/ )。当你在这个地区时,这是两个值得参观的好地方。

我们知道华盛顿特区的表中有一行,但是巴尔的摩呢?我们可以像前面一样运行一个快速的批处理查询,但是这一次我们将以选项卡的形式看到结果。

C:\Users\cbell\Downloads\world_x-db>mysqlsh --uri=root@localhost:3306 --sql  -e "SELECT Name, Info FROM world_x.city WHERE CountryCode = 'USA' AND DISTRICT = 'Maryland'"
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):
Name    Info
Baltimore       {"Population": 651154}

现在我们知道两个城市都有行,我们需要做的就是构造我们想要插入的 JSON。在这种情况下,我们将使用另一个 JSON 函数来添加新数据。但首先,让我们看看这些数据是什么样的。在这种情况下,我们希望包括网站的名称、网站的 URL 和网站的类型(例如,博物馆、景点)。为了能够为每个城市添加多个站点,我们将以 JSON 数组的形式添加新数据。这可能看起来很混乱,但是让我们看看巴尔的摩的例子。下面显示了包含现有数据和新数据的完整 JSON 文档。我以一种典型的方式对它进行了格式化,您将看到 JSON 文档使用缩进。

{
      "Population": 651154,
      "Places_of_interest": [
            {
                  "name":"National Harbor",
                  "URL":"https://www.nationalharbor.com/",
                  "type":"attraction"
            }
      ]
}

此时,您可能想知道如何确保 JSON 文档的格式正确。对于大多数人来说,这来自于使用 JSON 的经验。然而,MySQL 提供了一个名为JSON_VALID()的 JSON 函数,您可以用它来验证 JSON 文档。只需将字符串作为参数传递。对于有效的文档,应该得到值 1,对于有错误的文档,应该得到值 0,如下所示。在这里,我们看到文件是有效的。

SQL > SELECT JSON_VALID('{"Population": 651154, "Places_of_interest": [{"name": " National Harbor ", "URL":" https://www.nationalharbor.com/","type":"attraction"}]}')\G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
JSON_VALID('{"Population": 651154, "Places_of_interest": [{"name": " National Harbor ", "URL":" https://www.nationalharbor.com/","type":"attraction"}]}'): 1
1 row in set (0.0005 sec)

现在我们准备更新表中的数据。为此,我们将使用 UPDATE SQL 语句,用上面的新 JSON 文档替换信息列。但是,我们必须用更传统的字符串重新格式化文档。您可以在字符串中保留空格和换行符,但这样做并不常见。相反,我们希望形成一个用单引号括起来的字符串。但是首先,我们需要表中该行的键。city 表有一个名为 ID 的关键字字段。我们去查两个城市的身份证。

SQL > SELECT ID, Name FROM world_x.city WHERE Name IN ('Washington', 'Baltimore');
+------+------------+
| ID   | Name       |
+------+------------+
| 3809 | Baltimore  |
| 3813 | Washington |
+------+------------+
2 rows in set (0.0053 sec)

现在,让我们做更新。下面是一个典型的 SQL UPDATE命令,用于替换表中特定行的列。这里没有什么不寻常的,但是请注意,我们使用 SQL 执行的\G选项以更容易阅读的形式显示结果。

SQL > UPDATE world_x.city set Info = '{"Population": 651154,"Places_of_interest":[{"name":"National Harbor","URL":"https://www.nationalharbor.com/","type":"attraction"}]}' WHERE ID = 3809;
Query OK, 1 row affected (0.0499 sec)

Rows matched: 1  Changed: 1  Warnings: 0

SQL > SELECT Name, District, Info FROM world_x.city WHERE ID = 3809\G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Baltimore
District: Maryland
    Info: {"Population": 651154, "Places_of_interest": [{"URL": "https://www.nationalharbor.com/", "name": "National Harbor", "type": "attraction"}]}
1 row in set (0.0008 sec)

在这里,我们看到我们已经成功地更新(替换)了 JSON 文档。但是输出不容易阅读。为了更容易阅读,让我们使用JSON_PRETTY()函数,它将输出重新格式化为更令人满意的布局。下面显示了添加了函数的相同查询。那不是更好读吗?

SQL > SELECT Name, District, JSON_PRETTY(Info) FROM world_x.city WHERE ID = 3809\G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
             Name: Baltimore
         District: Maryland
JSON_PRETTY(Info): {
  "Population": 651154,
  "Places_of_interest": [
    {
      "URL": "https://www.nationalharbor.com/",
      "name": "National Harbor",
      "type": "attraction"
    }
  ]
}
1 row in set (0.0005 sec)

现在,让我们看看使用该列的真实更新完成的其他更新。这里,我们将使用另一个名为 JSON_MERGE_PRESERVE()的特殊 JSON 函数,它合并两个 JSON 文档并保留数组(当合并两个数组时)。对于这个例子,它有效地将现有的 JSON 文档与我们添加的新信息合并在一起。

注意

有几种方法可以实现这一更新,但这是精明的数据库管理员常用的一种方法。

为了实现这一点,让我们首先从行中获取当前的 JSON 文档。我们将使用一个局部变量(以@开头)来存储使用SELECT语句的SELECT…INTO版本的结果,如下所示。在这里,我们将值保存到@var1并显示它。

SQL > SELECT Info FROM world_x.city WHERE ID = 3813 INTO @var1;
Query OK, 1 row affected (0.0007 sec)

SQL > SELECT @var1;
+------------------------+
| @var1                  |
+------------------------+
| {"Population": 572059} |
+------------------------+
1 row in set (0.0004 sec)

现在我们可以构建我们想要添加的新信息。下面展示了仅包含新数据的 JSON 文档(population 已经在该行中)。但是不要担心,我们将合并文档。

{
      "Places_of_interest":[
            {
                  "name":"Smithsonian National Air and Space Museum",
                  "URL":"https://airandspace.si.edu/",
                  "type":"museum"
            }
      ]
}

接下来,我们可以使用 JSON 文档和变量来更新行,如下所示。

SQL > UPDATE world_x.city SET Info = JSON_MERGE_PRESERVE(@var1, '{"Places_of_interest":[{"name":"Smithsonian National Air and Space Museum","URL":"https://airandspace.si.edu/","type":"museum"}]}') WHERE ID = 3813;
Query OK, 1 row affected (0.0784 sec)

Rows matched: 1  Changed: 1  Warnings: 0

请注意,我们现在添加了新信息,并保留了总体。酷。

SQL > SELECT Name, District, JSON_PRETTY(Info) FROM world_x.city WHERE ID = 3813\G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
             Name: Washington
         District: District of Columbia
JSON_PRETTY(Info): {
  "Population": 572059,
  "Places_of_interest": [
    {
      "URL": "https://airandspace.si.edu/",
      "name": "Smithsonian National Air and Space Museum",
      "type": "museum"
    }
  ]
}
1 row in set (0.0005 sec)

现在,如果我们只想检索Places_of_interest数组的值呢?在这种情况下,我们可以使用另一个名为JSON_EXTRACT()的 JSON 函数从数组中提取键和值。下面演示了这种技术。请注意以粗体突出显示的部分。这里,我们使用前面看到的路径表达式提取密钥。而且,我们正在对整个表进行查询,所以我们将获得 JSON 文档中具有Places_of_interest键的所有行。

SQL > SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL \G
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Baltimore
District: Maryland
  Sights: ["National Harbor"]
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Washington
District: District of Columbia
  Sights: ["Smithsonian National Air and Space Museum"]
2 rows in set (0.0119 sec)

好了,现在看起来容易多了,不是吗?这也是一个有点混乱的 SQL 命令。如果这一切看起来有点痛苦,你是对的,的确如此。在 SQL 中处理 JSON 数据需要借助 JSON 函数,但是这是一个额外的步骤,在语法上可能有点混乱。关于每个 JSON 函数的完整解释,请参阅在线 MySQL 参考手册。 1 我们将在下一章看到更多关于 JSON 函数的内容。

使用格式模式

如果您经常使用旧的 MySQL 客户端来查询具有宽行的数据,那么您很可能会像上面一样使用\G选项来以垂直格式显示结果,这使得读取数据更加容易。有了 shell,我们可以用几种方式显示数据。在这一节中,我们将看到在批处理模式下运行 shell 以各种格式显示数据的简短示例。正如您将看到的,选择格式有助于使数据更容易阅读(或者如果在脚本中阅读输出,则更容易摄取)。

回想一下,我们可以使用命令行选项--table--tabbed--vertical--json来设置 JSON 格式,有两种选择。选择的输出将影响输出在执行模式(SQL、Python 或 JavaScript)下的外观。对于本教程,我们将只看到 SQL 模式。

让我们从表格格式开始。下面以表格格式显示了在批处理模式下执行最后一个查询的结果。请注意,我们看到的输出类似于在 SQL 模式下交互运行时的输出。

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --table
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):
+------------+----------------------+-------------------------------------+
| Name       | District             | Sights                              |
+------------+----------------------+-------------------------------------+
| Baltimore  | Maryland             | ["National Harbor"]                 |
| Washington | District of Columbia | ["Smithsonian National Air and Space Museum"]                      |
+------------+----------------------+-------------------------------------+

接下来,让我们看看选项卡式格式。下面显示了以选项卡格式在批处理模式下执行最后一个查询的结果。注意,在这种情况下,输出是一个制表符分隔的视图。在清单中不容易看到,但是当在脚本中运行时,它使得输入输出很容易用制表符分开。

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --tabbed
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):
Name    District        Sights
Baltimore       Maryland        ["National Harbor"]
Washington      District of Columbia    ["Smithsonian National Air and Space Museum"]

接下来,我们来看看垂直格式。下面显示了使用垂直格式在批处理模式下执行最后一个查询的结果。注意,在这种情况下,输出类似于在 SQL 模式下使用\G选项。

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --vertical
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Baltimore
District: Maryland
  Sights: ["National Harbor"]
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Washington
District: District of Columbia
  Sights: ["Smithsonian National Air and Space Museum"]

接下来,让我们看看原始的 JSON 格式。下面显示了使用原始 JSON 格式在批处理模式下执行最后一个查询的结果。注意,在这种情况下,输出与我们通常在 SQL 模式下看到的非常不同。事实上,我们将输出视为一系列 JSON 文档,尽管没有格式化。

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --json=raw
{"password":"Please provide the password for 'root@localhost:3306': "}
∗∗∗∗∗∗∗∗∗∗
{"prompt":"Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): "}

{"executionTime":"0.0063 sec","info":"","rows":[{"Name":"Baltimore","District":"Maryland","Sights":"[\"National Harbor\"]"},{"Name":"Washington","District":"District of Columbia","Sights":"[\"Smithsonian National Air and Space Museum\"]"}],"warningCount":0,"warningsCount":0,"warnings":[],"hasData":true,"affectedRowCount":0,"affectedItemsCount":0,"autoIncrementValue":0}

最后,我们来看看漂亮的 JSON 格式。到目前为止,输出相当简洁。然而,漂亮的 JSON 格式有点冗长。清单 3-11 显示了以批处理模式执行最后一个查询的结果,格式为漂亮的 JSON 格式。在这种情况下,它添加了空白和新行,以便于阅读。

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --json=pretty
{
    "password": "Please provide the password for 'root@localhost:3306': "
}
∗∗∗∗∗∗∗∗∗∗
{
    "prompt": "Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): "
}

{
    "executionTime": "0.0033 sec",
    "info": "",
    "rows": [
        {
            "Name": "Baltimore",
            "District": "Maryland",
            "Sights": "[\"National Harbor\"]"
        },
        {
            "Name": "Washington",
            "District": "District of Columbia",
            "Sights": "[\"Smithsonian National Air and Space Museum\"]"
        }
    ],
    "warningCount": 0,
    "warningsCount": 0,
    "warnings": [],
    "hasData": true,
    "affectedRowCount": 0,
    "affectedItemsCount": 0,
    "autoIncrementValue": 0
}

Listing 3-11The JSON pretty Format

请注意,输出更加冗长,甚至来自 shell 的消息也是 JSON 格式的,但是这确实有助于更好地读取 JSON 数据。

代码/命令历史

像它的前身一样,shell 允许您通过命令历史列表调用最后输入的命令。与原始客户端不同,shell 还允许您搜索历史记录。这在编写脚本时特别有用,因为它允许您搜索以前使用过的操作。

要搜索命令历史,请随时按下 CTRL+R 。这将启动反向搜索,通过命令进行反向搜索。提示会发生变化,表明您正在搜索,您可以键入要搜索的命令的前几个字符。搜索时将显示找到的第一个命令,如下所示。如果这不是你正在寻找的命令,你可以再次按下 CTRL+R 来获得下一个匹配,或者按下 CTRL+C 来取消。如果按下回车,找到的命令将被执行。

(reverse-i-search)`SHOW': SHOW TABLES FROM world_x;

向前搜索有一点不同,当你已经处于搜索模式时,向前搜索仍然有效。也就是说,按下 CTRL+S 将向前搜索历史记录,但如果您不在搜索模式下,则不能向前搜索。然而,一旦你掌握了窍门,使用起来就非常方便。与反向搜索一样,正向搜索会更改提示,如下所示。

(i-search)`SHOW': SHOW DATABASES;

您还可以配置存储在历史记录中的项目数量(默认为 100),以及在名为~/.mysqlsh/history(Windows 上为%AppData%\MySQL\mysqlsh\history)的文件中查看历史记录。但是,您必须使用\history 命令保存历史,或者将 shell 配置为自动保存历史。我们将在后面的章节中看到如何做到这一点。您可以使用\history 命令随时查看历史列表,如下所示。

SQL > \history
    1  \history
    2  \connect root@localhost:3306
    3  SHOW DATABASES;
    4  SHOW TABLES FROM world_x;
    5  SHOW VARIABLES LIKE '%ssh%';
    6  SHOW VARIABLES LIKE '%ssl%';

\history 命令还允许您删除历史记录中的一个或多个条目,清除历史记录(在切换模式时很有用),并保存历史记录。命令选项如下所示。

  • \history del 2-4:从历史记录中删除条目 2、3 和 4。

  • \history clear:清除本次会话的历史记录。

  • \history save:保存历史到文件。

注意

只有那些交互输入的命令才会保存在历史记录中。批处理执行不会将命令保存到历史文件中。

保存密码

现在让我们来讨论 shell 的最新和最有成效的特性之一——秘密存储。这是通过称为可插拔密码存储的功能实现的,该功能支持多种存储机制,包括秘密存储、钥匙串等。

它允许您安全地存储常用的密码,这使得使用 MySQL Shell 更加容易和安全。您可以使用秘密储存装置(如钥匙串)来存储服务器连接的密码。您以交互方式输入连接的密码,该密码作为连接的凭证与服务器 URL 一起存储。

小费

参见 https://dev.mysql.com/doc/mysql-shell/8.0/en/mysql-shell-pluggable-password-store.html 了解更多关于使用可插拔密码存储器的信息。

事实上,到目前为止,您已经看到该消息多次出现在 shell 的输出中,在所有示例中,我只需对该提示按 enter 键就可以回答“no ”,这告诉 shell 不要存储密码。

Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):

现在,让我们补救一下,并在我们的系统上永久保存该密码!清单 3-12 显示了运行 shell 来执行一个简单查询的脚本。第一次,我告诉 shell 记住密码。第二次,我不再需要记住密码,shell 也不会提示我输入密码。

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --vertical
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): Y
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Baltimore
District: Maryland
  Sights: ["National Harbor"]
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Washington
District: District of Columbia
  Sights: ["Smithsonian National Air and Space Museum"]

C:\Users\cbell>mysqlsh --uri=root@localhost:3306 --sql -e "SELECT Name, District, JSON_EXTRACT(info, '$.Places_of_interest[∗].name') as Sights FROM world_x.city WHERE JSON_EXTRACT(info, '$.Places_of_interest') IS NOT NULL" --vertical
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 1\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Baltimore
District: Maryland
  Sights: ["National Harbor"]
∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗ 2\. row ∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗∗
    Name: Washington
District: District of Columbia
  Sights: ["Smithsonian National Air and Space Museum"]

Listing 3-12Saving Passwords with the Secret Store

如果您想在忘记或更改密码时重置密码,可以使用一个特殊的对象(全局变量),该对象是一个可用于自定义可插拔密码功能的类。由于定制 shell 是一个更大的主题,我们将在下一节讨论如何定制 shell,在下一节我们还将看到如何重置存储的密码。

定制 Shell

我们将讨论的最后一个教程是如何定制 shell。您可以更改几个控制 shell 操作方式的参数。这包括更改提示以及自动完成、等待时间、输出格式等等。让我们从它是如何工作的开始。

有三种方法可以在 shell 中设置配置选项。您可以使用\option命令来列出、设置甚至取消设置选项及其值,或者您可以在 Python 或 JavaScript 模式下使用shell.option对象,或者您可以修改磁盘上的配置文件。让我们来看看这些技术的实际应用。

使用\option命令

\option命令在任何模式下都有效。\option命令是设置选项的更常用方法。清单 3-13 显示了\option命令的帮助文本以及配置命令历史的选项列表。

Py > \help \option
NAME
      \option - Allows working with the available shell options.

SYNTAX
      \option [args]

DESCRIPTION
      The given [args] define the operation to be done by this command, the
      following values are accepted

      - -h, --help [<filter>]: print help for the shell options matching
        filter.
      - -l, --list [--show-origin]: list all the shell options.
      - <shell_option>: print value of the shell option.
      - <shell_option> [=] <value> sets the value for the shell option.
      - --persist causes an option to be stored on the configuration file
      - --unset resets an option value to the default value.
Py > \option --help history
 history.autoSave           Shell's history autosave.
 history.maxSize            Shell's history maximum size
 history.sql.ignorePattern  Shell's history ignore list.

Py > \option history.autoSave
false

Py > \option history.maxSize
1000

Py > \option history.sql.ignorePattern
∗IDENTIFIED∗:∗PASSWORD∗

Listing 3-13Using the \option Command

这里,我们看到了一个使用\option \help命令列出命令历史功能可用选项的例子。虽然这仅仅显示了选项的名称,但是我们可以使用\option命令来查看每个特定选项的值。如果你想看到所有可用的选项及其值,使用\option --list命令。

小费

如果设置选项时没有使用--persist参数,当 shell 关闭时,更改不会被保存。您必须使用参数来保存更改,以便在以后的执行中保持(保存)更改。

回想一下上一节,我们可以让 shell 自动保存历史,这样我们就不必手动保存了。正如我们在清单 3-13 中看到的,我们可以将history.autoSave选项设置为true,如下所示。注意,这里我们只是使用赋值参数(等号)来设置值,然后保存(持久化)更改。

Py > \option --persist history.autoSave = true

使用shell.option对象

我们还可以通过使用shell.option对象和set()方法(为 shell 的当前执行设置值)或者使用set_perist()方法永久保存值,在其中一种脚本模式中设置选项。为了设置选项,我们使用选项类别和选项的名称作为引号(单引号或双引号)内的点字符串。例如,下面的代码设置了自动历史保存,就像我们在上一节中看到的那样。

Py > shell.options.set_persist("history.autoSave", True)

shell 对象有几个方法可以与选项一起使用,如下所示。

  • shell.options.set(<option_name>, <value>):将<option_name>设置为此会话的值,不保存更改。

  • shell.options.set_persist(<option_name>, <value>):将<option_name>设置为此会话的值,并将更改保存到配置文件。

  • shell.options.unset(<option_name>):将<option_name>重置为该会话的默认值,更改不会保存到配置文件中。

  • shell.options.unset_persist(<option_name>):将<option_name>重置为该会话的默认值,并将更改保存到配置文件。

清单 3-14 展示了一个使用 shell 对象和自动完成特性(通过按下 TAB 两次来启动)来取消设置值,将其更改为缺省值并保存它的例子。最后,我们看看如何将所有选项恢复到它们的默认值。

Py > shell.options.<TAB><TAB>
autocomplete.nameCache          devapi.dbObjectHandles          pager
batchContinueOnError            history.autoSave                passwordsFromStdin
credentialStore.excludeFilters  history.maxSize                 sandboxDir
credentialStore.helper          history.sql.ignorePattern       showWarnings
credentialStore.savePasswords   interactive                     useWizards
dba.gtidWaitTimeout             logLevel
defaultMode                     outputFormat
Py > shell.options.set("history.autoSave", True)

Py > print(shell.options["history.autoSave"])
True
Py > shell.options.unset_persist("history.autoSave")

Listing 3-14Using the shell.option Object

使用配置文件

更改和保留的选项以 JSON 格式存储在配置文件中。值在启动时读取,当您使用持久化功能时,设置会保存到配置文件中。因此,您还可以通过将选项添加到配置文件中来更改它们,或者如果选项已经存在,您可以在文件中更改它们并重新启动 shell 以使它们生效。下面显示了配置文件的一个示例。所有选项和值都作为键、值对存储在同一个 JSON 文档中。

C:\Users\cbell\AppData\Roaming\MySQL\mysqlsh>more options.json
{
    "history.autoSave": "true"
}

配置文件的位置是用户配置路径,该文件被命名为options.json。在 Windows 上,该文件位于%APPDATA%\MySQL\mysqlsh\options.json,或者在 Linux 上,位于~/.mysqlsh/options.json

第一次更改选项时会创建配置文件。虽然您可以编辑此文件来更改选项,但必须非常小心。这是因为该文件被视为内部文件,用户不能更改。如果您犯了一个错误,设置了错误的选项(比如拼错了名称),shell 可能不会启动并抛出一个错误。因此,您应该注意首先以交互方式设置选项,然后编辑文件来更改它。虽然这仍不被认为是“安全的”,但可以通过编辑文件来更改选项。

警告

不建议直接编辑options.json文件。

使用保存的密码

您可以在 shell 中配置的事情之一是可插入的密码身份验证,或者用更实际的术语来说,保存在 secret store 中的凭证。在这种情况下,我们可能想要撤销某些密码,因为我们已经更改了它们,或者我们可能想要查看存储了哪些凭证。

我们可以使用 shell 对象中的一个或多个函数与这个特性进行交互。例如,下面显示了如何列出存储的凭据。这将返回所有存储的凭据的列表(或者,如果缺少变量,则打印返回的列表)。在这种情况下,只存储一个凭据。请注意,不打印任何密码。

Py > shell.list_credentials()
[
    "root@localhost:3306"
]

以下函数允许您使用可插拔密码存储。您可以列出可用的秘密存储帮助程序,以及列出、存储和检索凭据。要使用其中的任何一个,您必须以一种脚本模式(Python 或 JavaScript)执行它们。然而,值得注意的是,由于命名约定的不同,Python 和 JavaScript 模式之间的方法名称略有不同。例如,JavaScript 名称遵循类似于 camelCase 的不同模式,Python 在名称中使用下划线。我们将在本书中使用 Python 示例。

  • cred_list = list_credentials():返回存储的所有凭证列表(无密码!)

  • delete_credential(<URI>):删除给定 URI 的凭证

  • delete_all_credentials():删除当前存储的所有凭证

  • cred_helpers = list_credential_helpers():返回凭证帮助者列表

  • store_credential(<URI>, [<password>]):存储给定 URI 的凭证,可选地指定密码(如果未提供,则提示输入密码)

如果您想要替换其中一个凭证——比方说更改与之相关的密码——您可以使用提供相同 URI 的shell.store_credential()方法,如下所示。在本例中,我省略了 password 参数,所以 shell 会提示输入密码。

Py > shell.store_credential("root@localhost:3306")
Please provide the password for 'root@localhost:3306': ∗∗∗∗∗∗∗∗∗∗

如果我们想刷新所有凭证,我们可以使用shell.delete_all_credentials()方法。

更改提示

最后,shell 允许您更改交互式会话的提示。如果您想要显示一个提醒或类似的提示,例如使用不同的数据库或服务器,您可能需要这样做。

更改提示需要编辑系统上的文件。这个文件称为提示主题文件,可以使用MYSQLSH_PROMPT_THEME环境变量或者将主题模板文件保存到 Linux 上的~/.mysqlsh文件夹中的一个名为prompt.json的文件或者 Windows 上的%AppData%\MySQL\mysqlsh目录中来指定。

您可以在安装 shell 的目录share\mysqlsh\prompt中找到示例提示主题文件。例如,在 Windows 中,文件存储在c:\Program Files\MySQL\MySQL Shell 8.0中。下面显示了提示主题文件的列表。

10/04/2018  02:54 AM             1,245 prompt_16.json
10/04/2018  02:54 AM             2,137 prompt_256.json
10/04/2018  02:54 AM             1,622 prompt_256inv.json
10/04/2018  02:54 AM             2,179 prompt_256pl+aw.json
10/04/2018  02:54 AM             1,921 prompt_256pl.json
10/04/2018  02:54 AM               183 prompt_classic.json
10/04/2018  02:54 AM             2,172 prompt_dbl_256.json
10/04/2018  02:54 AM             2,250 prompt_dbl_256pl+aw.json
10/04/2018  02:54 AM             1,992 prompt_dbl_256pl.json
10/04/2018  02:54 AM             1,205 prompt_nocolor.json

在这里,我们看到了几个为各种常见的提示定制而预先格式化的文件。有不同的颜色主题以及在问题中显示的内容。例如,下面显示了经典主题:

{
  "symbols" : {
    "separator" : "-",
    "separator2" : "-",
    "ellipsis" : "-"
  },
  "segments": [
    {
      "text": "mysql"
    },
    {
      "text": "%mode%"
    }
  ]
}

如果您想进行自己的更改,可以在位于应用安装的share\mysqlsh\prompt目录下的README.prompt文件中找到记录的格式。您可以使用主题来指定特殊字体、终端颜色等。

但是,在创建提示主题文件时要小心,因为如果在提示主题文件中发现错误,将会打印一条错误消息并使用默认的提示主题。我建议在构建自己的提示主题文件之前,花些时间阅读一下README.prompt文件并研究一下示例。此外,请记住,这些文件可能会指定依赖于平台的设置,并且可能不会普遍适用。

摘要

MySQL Shell 代表了 MySQL 用户生产力的一次重大飞跃。shell 不仅是一个更好的 MySQL 客户端,它还是一个代码编辑器和测试环境。在这一章中,我们对 shell 及其主要特性进行了一个简短的浏览,包括内置命令、如何格式化输出,甚至如何定制 shell。在接下来的章节中,我们将再次应用我们到目前为止所学到的知识,探索如何在各种任务中使用 shell。

虽然在本章中我们还没有学到关于 MySQL Shell 的所有知识,但是我们已经了解了它是如何工作的,以及如何使用 MySQL Shell 提高工作效率。如果您想了解构成 MySQL Shell 的所有细微差别,请参阅在线用户指南( https://dev.mysql.com/doc/mysql-shell/8.0/en/ )。

在下一章中,我们将进行一次使用 SQL 数据库的向导之旅。我们将看到使用 SQL 接口的简要概述,但是我们将把重点放在使用 X DevAPI 处理关系数据库上。如果您非常熟悉 SQL 数据库和使用 SQL 命令,您可能希望浏览本章的 SQL 部分,然后浏览第五章中的示例,这些示例演示了如何将 MySQL Shell 用于 SQL 数据库,包括如何使用新的 X DevAPI for SQL 数据库。

Footnotes 1

https://dev.mysql.com/doc/refman/8.0/en/json.html