跳转到内容

输入关键词开始搜索文档。

MySQL

最后更新 查看 Markdown 源文件@flue/mysql

快速开始

使用 MySQL 蓝图为现有 Flue 项目添加持久化共享 MySQL 存储。在终端或你选择的编码智能体中运行以下命令:

flue add database mysql

概述

MySQL 蓝图会安装 @flue/mysql 和 mysql2,并在源代码根目录创建 db.ts。生成的适配器使用连接池进行普通查询,并为每个事务保持在一个签出的连接上:

src/db.ts (简化版)
import { mysql, type MysqlQuery } from '@flue/mysql';
import mysql2 from 'mysql2/promise';

const pool = mysql2.createPool(process.env.MYSQL_URL!);

const toRows = (result: unknown): Record<string, unknown>[] =>
  Array.isArray(result) ? result.map((row) => ({ ...row })) : [];

export default mysql({
  query: async (text, params = []) => {
    const [result] = await pool.execute(text, params);
    return toRows(result);
  },
  transaction: async <T>(fn: (tx: { query: MysqlQuery }) => Promise<T>) => {
    const connection = await pool.getConnection();
    await connection.beginTransaction();
    // ...
  },
  close: () => pool.end(),
});

Flue 在构建时发现适配器并将其连接到生成的 Node 服务器。启动时,它会创建并验证所需的 MySQL 8 InnoDB 表。规范的智能体对话、不可变附件和已接受的提交随后会在进程替换后得以保留。副本可以共享持久状态,但每个智能体实例仍然需要一个活动的 Node 所有者。应用业务数据仍由应用自行管理。此蓝图仅适用于 Node 目标,因为 Cloudflare 部署使用 Durable Object SQLite。

配置

变量用途
MYSQL_URL必需 — MySQL 连接字符串,由你的数据库提供商提供。

驱动在运行时读取此值。通过你平台的密钥存储提供它,永远不要提交它,并在提供商需要时配置 mysql2 TLS 选项。对于本地开发,vite dev 会加载项目 .env 文件,而 flue run --env <file> 会加载任何 .env 格式的文件。

蓝图会安装 @flue/mysql 和 mysql2,然后在源代码根目录创建 db.ts。Flue 在构建时发现该文件,并将其连接到生成的 Node 服务器。

@flue/mysql 支持 Node.js 目标上的 MySQL 8 和 InnoDB。Cloudflare 目标会自动使用 Durable Object SQLite,并在构建时拒绝 db.ts。有关按目标的持久化信息,请参阅数据库。

使用自定义驱动

@flue/mysql 不捆绑生产驱动。它接受一个运行器,因此你的应用拥有连接池、TLS、凭证和连接生命周期。规范的 mysql2 运行器使用 pool.execute() 进行普通查询,每个回调事务使用一个签出的连接:

src/db.ts
import { mysql, type MysqlQuery } from '@flue/mysql';
import mysql2 from 'mysql2/promise';

const pool = mysql2.createPool(process.env.MYSQL_URL!);

const toRows = (result: unknown): Record<string, unknown>[] =>
  Array.isArray(result) ? result.map((row) => ({ ...row })) : [];

export default mysql({
  query: async (text, params = []) => {
    const [result] = await pool.execute(text, params);
    return toRows(result);
  },
  transaction: async <T>(fn: (tx: { query: MysqlQuery }) => Promise<T>) => {
    const connection = await pool.getConnection();
    try {
      await connection.beginTransaction();
      const result = await fn({
        query: async (text, params = []) => {
          const [rows] = await connection.execute(text, params);
          return toRows(rows);
        },
      });
      await connection.commit();
      return result;
    } catch (error) {
      await connection.rollback();
      throw error;
    } finally {
      connection.release();
    }
  },
  close: () => pool.end(),
});

运行器使用 ? 占位符并返回普通行对象。事务回调中的每个查询都必须使用签出的连接;通过连接池发出这些调用可能会将工作转移到另一个连接,从而脱离事务。

迁移

适配器的 migrate() 钩子会在生成的 Node 服务器启动时自动运行。它会幂等地创建 Flue 的 flue_* 表,验证完整架构,然后标记其版本。所有事务表都使用 InnoDB。没有单独的迁移命令,由较新 Flue 版本写入的数据库会拒绝启动,而不是冒不兼容写入的风险。

存储内容

Flue 数据库存储运行时状态,而不是整个应用。

由 Flue 存储:

  • 规范的智能体对话流和压缩记录;
  • 不可变附件负载;
  • 已接受的直接提示和 dispatch(...) 提交;
  • 持久化提交声明、租约和结算记录。

不由 Flue 存储:

  • 沙盒文件和已安装的依赖项;
  • 外部 API 副作用;
  • 应用拥有的业务数据;
  • 提供商凭证或密钥。

有关恢复行为,请参阅持久性, 有关适配器契约,请参阅数据持久化 API。

何时选择 MySQL

当你的 Node 部署已经运行 MySQL 8,或者当替换进程和多个副本需要在 InnoDB 支持的数据库中存储持久化智能体状态时,请选择 MySQL。每个智能体实例保留一个活动所有者。对于单主机持久化,文件支持的 sqlite() 可能更简单。当 Postgres 是你现有的操作标准时,请选择 @flue/postgres, 或者对于 SQLite 和 libSQL 工作负载,请选择 @flue/libsql。