⌘+k ctrl+k
1.3 (稳定版)
搜索快捷键 cmd + k | ctrl + k
MySQL 扩展

mysql 扩展允许 DuckDB 直接从运行中的 MySQL 实例读写数据。数据可以直接从底层 MySQL 数据库查询。数据可以从 MySQL 表加载到 DuckDB 表中,反之亦然。

安装和加载

要安装 mysql 扩展,请运行

INSTALL mysql;

该扩展在首次使用时会自动加载。如果您希望手动加载,请运行

LOAD mysql;

从 MySQL 读取数据

要使 DuckDB 能够访问 MySQL 数据库,请使用 ATTACH 命令并指定 mysqlmysql_scanner 类型

ATTACH 'host=localhost user=root port=0 database=mysql' AS mysqldb (TYPE mysql);
USE mysqldb;

配置

连接字符串以 key=value 对的形式确定连接 MySQL 的参数。任何未提供的选项将按照下表中的默认值进行替换。连接信息也可以通过环境变量指定。如果未明确提供任何选项,MySQL 扩展会尝试从环境变量中读取。

设置 默认值 环境变量
database NULL MYSQL_DATABASE
host localhost MYSQL_HOST
password   MYSQL_PWD
port 0 MYSQL_TCP_PORT
socket NULL MYSQL_UNIX_PORT
user 当前用户 MYSQL_USER
ssl_mode 首选  
ssl_ca    
ssl_capath    
ssl_cert    
ssl_cipher    
ssl_crl    
ssl_crlpath    
ssl_key    

通过 Secrets 配置

MySQL 连接信息也可以通过Secrets指定。可以使用以下语法创建 Secret。

CREATE SECRET (
    TYPE mysql,
    HOST '127.0.0.1',
    PORT 0,
    DATABASE mysql,
    USER 'mysql',
    PASSWORD ''
);

当调用 ATTACH 时,将使用 Secret 中的信息。我们可以将连接字符串留空以使用 Secret 中存储的所有信息。

ATTACH '' AS mysql_db (TYPE mysql);

我们可以使用连接字符串来覆盖单个选项。例如,在仍然使用相同凭据的情况下连接到不同的数据库,我们可以只覆盖数据库名称,如下所示。

ATTACH 'database=my_other_db' AS mysql_db (TYPE mysql);

默认情况下,创建的 Secret 是临时的。可以通过CREATE PERSISTENT SECRET 命令持久化 Secret。持久化 Secret 可以在不同会话间使用。

管理多个 Secrets

命名 Secret 可用于管理与多个 MySQL 数据库实例的连接。Secret 可以在创建时被赋予名称。

CREATE SECRET mysql_secret_one (
    TYPE mysql,
    HOST '127.0.0.1',
    PORT 0,
    DATABASE mysql,
    USER 'mysql',
    PASSWORD ''
);

然后,可以在 ATTACH 中使用 SECRET 参数显式引用该 Secret。

ATTACH '' AS mysql_db_one (TYPE mysql, SECRET mysql_secret_one);

SSL 连接

ssl 连接参数可用于建立 SSL 连接。以下是支持的参数说明。

设置 描述
ssl_mode 用于连接到服务器的安全状态:disabled, required, verify_ca, verify_identity 或 preferred (默认: preferred)
ssl_ca 证书颁发机构 (CA) 证书文件的路径名
ssl_capath 包含受信任 SSL CA 证书文件的目录路径名
ssl_cert 客户端公钥证书文件的路径名
ssl_cipher SSL 加密允许使用的密码列表
ssl_crl 包含证书吊销列表的文件的路径名
ssl_crlpath 包含证书吊销列表文件的目录路径名
ssl_key 客户端私钥文件的路径名

读取 MySQL 表

MySQL 数据库中的表可以像普通的 DuckDB 表一样被读取,但底层数据是在查询时直接从 MySQL 读取的。

SHOW ALL TABLES;
名称
signed_integers
SELECT * FROM signed_integers;
t s m i b
-128 -32768 -8388608 -2147483648 -9223372036854775808
127 32767 8388607 2147483647 9223372036854775807
NULL NULL NULL NULL NULL

最好在 DuckDB 中创建 MySQL 数据库的副本,以防止系统持续从 MySQL 重新读取表,特别是对于大型表。

数据可以使用标准 SQL 从 MySQL 复制到 DuckDB,例如

CREATE TABLE duckdb_table AS FROM mysqlscanner.mysql_table;

写入数据到 MySQL

除了从 MySQL 读取数据之外,还可以使用标准 SQL 查询在 MySQL 中创建表、将数据摄取到 MySQL 以及对 MySQL 数据库进行其他修改。

这允许您使用 DuckDB,例如,将存储在 MySQL 数据库中的数据导出到 Parquet,或者将 Parquet 文件中的数据读取到 MySQL。

下面是关于如何在 MySQL 中创建新表并向其中加载数据的简要示例。

ATTACH 'host=localhost user=root port=0 database=mysqlscanner' AS mysql_db (TYPE mysql);
CREATE TABLE mysql_db.tbl (id INTEGER, name VARCHAR);
INSERT INTO mysql_db.tbl VALUES (42, 'DuckDB');

支持对 MySQL 表的许多操作。所有这些操作都直接修改 MySQL 数据库,后续操作的结果可以使用 MySQL 读取。请注意,如果不需要进行修改,可以使用 READ_ONLY 属性运行 ATTACH,这将阻止对底层数据库进行修改。例如

ATTACH 'host=localhost user=root port=0 database=mysqlscanner' AS mysql_db (TYPE mysql, READ_ONLY);

支持的操作

以下是支持的操作列表。

CREATE TABLE

CREATE TABLE mysql_db.tbl (id INTEGER, name VARCHAR);

INSERT INTO

INSERT INTO mysql_db.tbl VALUES (42, 'DuckDB');

SELECT

SELECT * FROM mysql_db.tbl;
id 名称
42 DuckDB

COPY

COPY mysql_db.tbl TO 'data.parquet';
COPY mysql_db.tbl FROM 'data.parquet';

您也可以使用COPY FROM DATABASE 语句创建数据库的完整副本。

COPY FROM DATABASE mysql_db TO my_duckdb_db;

UPDATE

UPDATE mysql_db.tbl
SET name = 'Woohoo'
WHERE id = 42;

DELETE

DELETE FROM mysql_db.tbl
WHERE id = 42;

ALTER TABLE

ALTER TABLE mysql_db.tbl
ADD COLUMN k INTEGER;

DROP TABLE

DROP TABLE mysql_db.tbl;

CREATE VIEW

CREATE VIEW mysql_db.v1 AS SELECT 42;

CREATE SCHEMADROP SCHEMA

CREATE SCHEMA mysql_db.s1;
CREATE TABLE mysql_db.s1.integers (i INTEGER);
INSERT INTO mysql_db.s1.integers VALUES (42);
SELECT * FROM mysql_db.s1.integers;
i
42
DROP SCHEMA mysql_db.s1;

事务

CREATE TABLE mysql_db.tmp (i INTEGER);
BEGIN;
INSERT INTO mysql_db.tmp VALUES (42);
SELECT * FROM mysql_db.tmp;

这将返回

i
42
ROLLBACK;
SELECT * FROM mysql_db.tmp;

这将返回一个空表。

DDL 语句在 MySQL 中不是事务性的。

在 MySQL 中运行 SQL 查询

mysql_query 表函数

mysql_query 表函数允许您在已附加的数据库中运行任意读取查询。mysql_query 接受要执行查询的已附加 MySQL 数据库的名称以及要执行的 SQL 查询。查询结果将被返回。单引号字符串通过重复两次单引号来转义。

mysql_query(attached_database::VARCHAR, query::VARCHAR)

例如

ATTACH 'host=localhost database=mysql' AS mysqldb (TYPE mysql);
SELECT * FROM mysql_query('mysqldb', 'SELECT * FROM cars LIMIT 3');

mysql_execute 函数

mysql_execute 函数允许在 MySQL 中运行任意查询,包括更新数据库模式和内容的语句。

ATTACH 'host=localhost database=mysql' AS mysqldb (TYPE mysql);
CALL mysql_execute('mysqldb', 'CREATE TABLE my_table (i INTEGER)');

设置

名称 描述 默认值
mysql_bit1_as_boolean 是否将 BIT(1) 列转换为 BOOLEAN true
mysql_debug_show_queries 调试设置:将所有发送到 MySQL 的查询打印到标准输出 false
mysql_experimental_filter_pushdown 是否使用过滤器下推(目前处于实验阶段) false
mysql_tinyint1_as_boolean 是否将 TINYINT(1) 列转换为 BOOLEAN true

模式缓存

为避免持续从 MySQL 获取模式数据,DuckDB 会缓存模式信息——例如表的名称、它们的列等。如果通过与 MySQL 实例的不同连接对模式进行了更改,例如向表中添加了新列,则缓存的模式信息可能会过时。在这种情况下,可以执行 mysql_clear_cache 函数来清除内部缓存。

CALL mysql_clear_cache();