使用 CONNECT SE 在 Docker 中通过演示示例访问远程 JSON 数据

CONNECT 是一种存储引擎(SE)插件,用于访问外部、本地或远程数据。在本博客中,我们将展示如何在 Docker 容器中安装 CONNECT 存储引擎,以及如何在容器之间共享 JSON 数据。

在 Docker 中启用 CONNECT SE 插件

CONNECT SE 需要安装在容器内部才能使用。要了解如何操作,请查看 在 MariaDB Docker Library 容器中安装插件

在远程服务器上创建 JSON 数据

CONNECT SE 对于 MariaDB 最重要的特性是能够灵活地从各种数据源创建表,例如同一数据库和其他 DMBS 的表或不同格式的文件。您可以在 CONNECT 表类型 中阅读更多内容。在这里我们将使用 CONNECT JSON 表类型

我们将使用两个容器,mariadb-remote 作为存储源数据的服务器,以及 mariadb-local 作为我们将从中创建源服务器表的本地服务器。因此,我们首先在源服务器上创建 JSON 数据。

  • 为了进行远程连接而创建网络
$ docker network create mynetwork
  • 使用镜像 my_connect_img 启动源容器 mariadb-remote,并通过指定容器启动期间创建的用户的权限,您可以在 上一篇博客 中找到相关信息。
$ docker run --rm -d --name mariadb-remote -v$PWD/local_init_dir1:/docker-entrypoint-initdb.d \
  -e MARIADB_USER=anel  -e MARIADB_PASSWORD=anel -e MARIADB_DATABASE=web_users \
  --network mynetwork -e MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1 my_connect_img
  • 验证用户的权限
$ docker exec -it mariadb-remote mariadb -uanel -panel web_users  -e "show grants for current_user;"
+--------------------------------------------------------------------------------------------------------------+
| Grants for anel@%                                                                                            |
+--------------------------------------------------------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO `anel`@`%` IDENTIFIED BY PASSWORD '*1F81CD5C3293B40FA2B98C69E8495874BE999E34' |
| GRANT ALL PRIVILEGES ON `web\_users`.* TO `anel`@`%`                                                         |
+--------------------------------------------------------------------------------------------------------------+
  • 由于我们是从已安装 CONNECT 的镜像构建的,因此无需检查 SE 的存在性。
  • 创建 JSON 数据。

我们将使用来自 users1users2 的数据,通过 SQL 语句将它们存储在一个文件中,并使用 表发现 功能从该文件创建 CONNECT 表。步骤如下:

— 启动客户端

docker exec -it mariadb-remote mariadb -uanel -panel web_users

— 执行查询以使用 set statementselect into outfile 创建文件。

set @web_users='[{
  "id": 1,
  "name": "Leanne Graham",
  "username": "Bret",
  "email": "Sincere@april.biz",
  "address": {
    "street": "Kulas Light",
    "suite": "Apt. 556",
    "city": "Gwenborough",
    "zipcode": "92998-3874",
    "geo": {
      "lat": "-37.3159",
      "lng": "81.1496"
    }
  },
  "phone": "1-770-736-8031 x56442",
  "website": "hildegard.org",
  "company": {
    "name": "Romaguera-Crona",
    "catchPhrase": "Multi-layered client-server neural-net",
    "bs": "harness real-time e-markets"
  }
},

{
  "id": 2,
  "name": "Ervin Howell",
  "username": "Antonette",
  "email": "Shanna@melissa.tv",
  "address": {
    "street": "Victor Plains",
    "suite": "Suite 879",
    "city": "Wisokyburgh",
    "zipcode": "90566-7771",
    "geo": {
      "lat": "-43.9509",
      "lng": "-34.4618"
    }
  },
  "phone": "010-692-6593 x09125",
  "website": "anastasia.net",
  "company": {
    "name": "Deckow-Crist",
    "catchPhrase": "Proactive didactic contingency",
    "bs": "synergize scalable supply-chains"
  }
}]';
SET STATEMENT SQL_MODE= CONCAT(@@SQL_MODE, ',NO_BACKSLASH_ESCAPES') FOR SELECT @web_users into outfile 'web_users.json';

— 从文件创建 CONNECT 表并查看结果

CREATE TABLE webusers
ENGINE=CONNECT TABLE_TYPE=JSON FILE_NAME='web_users.json';

MariaDB [web_users]> show create table webusers\G
*************************** 1. row ***************************
       Table: webusers
Create Table: CREATE TABLE `webusers` (
  `id` int(1) NOT NULL `JPATH`='$.id',
  `name` char(13) NOT NULL `JPATH`='$.name',
  `username` char(9) NOT NULL `JPATH`='$.username',
  `email` char(17) NOT NULL `JPATH`='$.email',
  `address_street` char(13) NOT NULL `JPATH`='$.address.street',
  `address_suite` char(9) NOT NULL `JPATH`='$.address.suite',
  `address_city` char(11) NOT NULL `JPATH`='$.address.city',
  `address_zipcode` char(10) NOT NULL `JPATH`='$.address.zipcode',
  `address_geo_lat` char(8) NOT NULL `JPATH`='$.address.geo.lat',
  `address_geo_lng` char(8) NOT NULL `JPATH`='$.address.geo.lng',
  `phone` char(21) NOT NULL `JPATH`='$.phone',
  `website` char(13) NOT NULL `JPATH`='$.website',
  `company_name` char(15) NOT NULL `JPATH`='$.company.name',
  `company_catchPhrase` char(38) NOT NULL `JPATH`='$.company.catchPhrase',
  `company_bs` char(32) NOT NULL `JPATH`='$.company.bs'
) ENGINE=CONNECT DEFAULT CHARSET=utf8mb4 `TABLE_TYPE`='JSON' `FILE_NAME`='web_users.json'
1 row in set (0.000 sec)

从远程服务器创建本地表

同样,我们需要创建一个名为 mariadb-local 的本地容器/服务器。以下是需要完成的步骤。

启动本地容器 mariadb-local(同样,我们在文件中定义权限并使用卷来应用它们)。

请按照之前的步骤安装插件,验证您的用户权限,重启服务器并检查插件是否工作。

$ docker run --rm -d --name mariadb-local \
-e MARIADB_USER=local_user  -e MARIADB_PASSWORD=local_user_pw -e MARIADB_DATABASE=test \
--network mynetwork -v$PWD/local_init_dir:/docker-entrypoint-initdb.d \
-e MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=1 my_connect_img
  • 使用远程连接到源服务器创建表

— 启动客户端

$ docker exec -it mariadb-local mariadb -ulocal_user -plocal_user_pw test

— 从远程服务器创建表(请注意,本地用户至少需要拥有 FILE 权限 才能用于向外的 CONNECT 表)。

MariaDB [test]> show tables;
Empty set (0.000 sec)

MariaDB [test]> CREATE TABLE local_web_user
                ENGINE = CONNECT
                TABLE_TYPE = MYSQL
                DBNAME = 'web_users'
                TABNAME = 'webusers'
                CONNECTION = 'mysql://anel:anel@mariadb-remote/';
Query OK, 0 rows affected (0.041 sec)

MariaDB [test]> show tables;
+----------------+
| Tables_in_test |
+----------------+
| local_web_user |
+----------------+
1 row in set (0.000 sec)

瞧,现在我们有了来自远程服务器的数据。

  • 创建新表

现在我们可以根据需要创建 InnoDB 表。

MariaDB [test]> create table new_table as select name, email, address_street from local_web_user;
MariaDB [test]> show create table new_table;
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                     |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| new_table | CREATE TABLE `new_table` (
  `name` char(13) NOT NULL,
  `email` char(17) NOT NULL,
  `address_street` char(13) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 |
+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.000 sec)

MariaDB [test]> select * from new_table;
+---------------+-------------------+----------------+
| name          | email             | address_street |
+---------------+-------------------+----------------+
| Leanne Graham | Sincere@april.biz | Kulas Light    |
| Ervin Howell  | Shanna@melissa.tv | Victor Plains  |
+---------------+-------------------+----------------+
2 rows in set (0.000 sec)

— 可以使用特定的查询从远程创建表

MariaDB [test]> CREATE TABLE local_web_user1 ENGINE = CONNECT TABLE_TYPE = MYSQL SRCDEF = 'SELECT * FROM web_users.webusers WHERE id=1' CONNECTION = 'mysql://anel:anel@mariadb-remote/';

结果

MariaDB [test]> select * from local_web_user1;
+----+---------------+----------+-------------------+----------------+---------------+--------------+-----------------+-----------------+-----------------+-----------------------+---------------+-----------------+----------------------------------------+-----------------------------+
| id | name          | username | email             | address_street | address_suite | address_city | address_zipcode | address_geo_lat | address_geo_lng | phone                 | website       | company_name    | company_catchPhrase                    | company_bs                  |
+----+---------------+----------+-------------------+----------------+---------------+--------------+-----------------+-----------------+-----------------+-----------------------+---------------+-----------------+----------------------------------------+-----------------------------+
|  1 | Leanne Graham | Bret     | Sincere@april.biz | Kulas Light    | Apt. 556      | Gwenborough  | 92998-3874      | -37.3159        | 81.1496         | 1-770-736-8031 x56442 | hildegard.org | Romaguera-Crona | Multi-layered client-server neural-net | harness real-time e-markets |
+----+---------------+----------+-------------------+----------------+---------------+--------------+-----------------+-----------------+-----------------+-----------------------+---------------+-----------------+----------------------------------------+-----------------------------+
1 row in set (0.001 sec)

结论和未来工作

本博客的主要目的是通过简单的语法从自定义数据源创建数据并从远程服务器获取数据,以验证 CONNECT SE 的强大功能。

这并非全部。我们刚刚看到了一个用例,仅仅触及了这个强大存储引擎的皮毛。

在下一篇博客中,我们将看到如何正确创建数据库连接字符串并将其与 CONNECT SE 一起使用。

欢迎反馈

如果您在此功能预览中遇到任何问题、设计问题或未按预期工作的边缘情况,请通过 MDEV 项目中的 JIRA 错误/功能请求告知我们。欢迎您在 Zulip 上讨论。