Turso + libSQL 深度拆解:AI Agent 时代,为什么我们需要「百万级数据库」新范式
一、背景:AI Agent 时代的数据困境
过去十年,我们习惯了「一个应用 + 一个数据库」的模式。MySQL、PostgreSQL、MongoDB,无论选哪个,架构逻辑都一样:所有用户、所有租户、所有 Agent 共享同一个数据库实例,通过表/字段/行级权限做隔离。
这个模式在 AI Agent 时代遇到了根本性的挑战。
问题的核心在于规模。
OpenAI CEO Sam Altman 说过:「未来 AI Agent 的数量会远超人类。」如果这个判断是对的,那么十年内,全球运行的 AI Agent 数量可能达到数十亿甚至万亿级别。每个 Agent 需要:
- 存储自己的记忆和上下文
- 管理自己处理的文件和资产
- 追踪自己负责的任务状态
- 保存与用户/其他 Agent 的交互历史
用一个共享数据库来服务万亿个 Agent?这条路走不通。
原因很简单:共享数据库的扩展模型是为「少量大实例」设计的。当你要支持百万级并发连接时,你需要分库分表、读写分离、连接池管理……这套东西复杂到令人窒息,而且成本极高。
更致命的是,共享数据库的故障是「单点」的。一个慢查询拖垮整个系统,所有 Agent 全部受影响。而 AI Agent 的工作流往往是长时间运行的,一个中途崩溃的 Agent 需要从头恢复——这在共享数据库架构下几乎无法优雅实现。
Turso 正是为这个问题而生的。
Turso 的核心理念是:** Millions of Databases. One Architecture.** 每个用户、每个 Agent、每个租户拥有自己独立的数据库实例,但运维复杂度与单个数据库无异。这不是分布式数据库的分片策略,而是一种自下而上的全新架构思路:基于 SQLite,把数据库做成一个可以无限复制的轻量文件。
本文将深度拆解 Turso 和 libSQL 的技术架构,探讨为什么它们代表了一种 AI 时代数据库的新范式。
二、核心概念:从「共享大数据库」到「多数据库架构」
2.1 传统数据库的扩展困境
在讨论 Turso 之前,我们需要先理解传统数据库在 AI 场景下的困境。
连接数问题是第一道墙。
以 PostgreSQL 为例,单个实例的 max_connections 默认是 100。即使通过 PgBouncer 等连接池工具做复用,单个节点的连接上限也就在几千到几万这个量级。而 AI Agent 的特点是:每个 Agent 都需要与数据库保持长期活跃的连接——因为 Agent 的工作流是长时间运行的,中间可能有多次读写操作。
想象一个场景:你有 100 万个 AI Agent 在运行。如果每个 Agent 保持一个数据库连接,那需要 100 万个连接。PostgreSQL 单机根本扛不住,水平扩展的分片方案复杂度又极高,而且分片后的跨分片查询几乎是无解的。
资源竞争是第二道墙。
共享数据库的第二个问题是:所有 Agent 共享同一个缓存池、同一套索引、同一个连接池。当一个 Agent 执行了一个重查询(比如全表扫描),其他所有 Agent 的延迟都会飙升。这是共享经济在数据库领域的反例:资源竞争导致整体效率下降。
故障隔离是第三道墙。
当共享数据库出现故障,所有 Agent 集体宕机。更要命的是,Agent 的工作流是状态敏感的。一个正在执行多步骤任务的 Agent,如果数据库突然不可用,它需要从上次成功的步骤重新开始。在共享数据库架构下,这种恢复几乎不可能做到细粒度控制。
2.2 多数据库架构的设计哲学
Turso 提出的多数据库架构(Many-Database Architecture),是对传统范式的根本性颠覆。
每个 Agent 拥有自己的数据库文件。
这不是逻辑隔离(行级权限、租户 ID),而是物理隔离。每个数据库是一个独立的 SQLite 文件,存储在 Turso 的边缘节点或本地设备上。Agent 与自己数据库的交互,不会影响其他 Agent 的数据库性能。
这带来几个关键变化:
故障天然隔离。 一个 Agent 的数据库出问题,只影响该 Agent,不会波及其他。
连接数不再是瓶颈。 每个 Agent 直接连接自己的本地数据库,不需要经过集中的连接池管理。百万 Agent = 百万独立连接,但每个连接都是本地的,没有网络延迟。
零冷启动。 SQLite 是嵌入式数据库,Agent 启动时数据库就已经在本地了。没有连接建立、没有查询编译缓存预热、没有网络 RTT。数据永远在线。
可复制到边缘。 Turso 的数据库可以实时同步到多个地理位置。Agent 在全球任何角落运行时,都可以从最近的边缘节点读取本地副本,写入通过增量同步传回主库。
2.3 libSQL:SQLite 的下一代继承者
Turso 的底层引擎不是标准 SQLite,而是 libSQL——一个从 SQLite 分叉并深度增强的版本。
libSQL 保留了 SQLite 的核心优势(轻量、可靠、事务 ACID、单文件),同时引入了现代应用需要的能力:
向量搜索(Vector Search):原生支持嵌入向量存储和相似度搜索,不需要安装任何扩展。RAG 工作流直接受益。
并发写入(Concurrent Writes):SQLite 传统上只支持单写入者。libSQL 通过 WAL 模式的增强和乐观锁机制,实现了多写入者的并发支持,且零冲突。
异步 I/O:集成 Linux io_uring 等现代异步原语,避免了同步 I/O 阻塞带来的性能抖动。
浏览器内运行:通过 WebAssembly + OPFS(Origin Private File System),libSQL 可以在浏览器中完整运行,数据持久化到本地存储。这意味着 Web 应用可以直接在客户端维护一个本地数据库。
云原生复制:libSQL 内置了多主复制的协议支持,支持离线写入和冲突解决,这是 SQLite 原生不支持的能力。
三、架构深度解析
3.1 Turso 的三层架构
Turso 的整体架构分为三层,每一层都有其独特的设计决策。
第一层:嵌入式引擎(libSQL)
这是整个系统的根基。libSQL 运行在 Agent 所在的进程/设备上,与 Agent 共享生命周期。
// libSQL 的核心抽象:一个 Database 实例就是一个文件
// 这是 libSQL 与传统数据库最本质的区别
let db = Database::open("agent_memory.db")?;
// 写入操作直接在本地执行,无网络开销
db.execute("INSERT INTO memory VALUES (?1, ?2)", params![agent_id, content])?;
在这个层面,数据库就是一个文件。这意味着:
- 数据库的备份 = 文件复制
- 数据库的迁移 = 文件传输
- 数据库的副本 = 文件同步
没有任何隐蔽的复杂性。
第二层:复制层(LibSQL Replication)
当 Agent 需要与其他 Agent 或服务端同步数据时,复制层负责将本地数据库的变更同步到远程节点。
// Turso SDK 中的复制配置
type ReplicatorConfig struct {
RemoteURL string // 远程 Turso 服务器地址
AuthToken string // 认证 Token
SyncInterval time.Duration // 同步间隔
PushOnWrite bool // 写入后立即推送
PullOnRead bool // 读取时按需拉取
}
// 创建一个带复制功能的数据库
db, err := turso.OpenDatabase(ctx, ReplicatorConfig{
RemoteURL: "libsql://my-db.turso.io",
AuthToken: "your-auth-token",
SyncInterval: 5 * time.Second,
PushOnWrite: true,
})
复制层采用 CRDT(无冲突复制数据类型) 机制处理并发写入冲突。当多个 Agent 同时修改同一数据库时,复制协议保证最终一致性,且不需要中央协调者。
第三层:边缘云层(Turso Cloud)
Turso Cloud 是管理百万级数据库实例的控制平面。它负责:
- 数据库的创建、销毁、计费
- 全球边缘节点的部署和数据路由
- 访问控制和认证
- 监控和日志
从开发者视角看,Turso Cloud 的体验极为简洁:
# 创建数据库(秒级完成)
turso db create my-agent-db
# 获取连接 URL
turso db show my-agent-db
# libsql://my-agent-db-[random].turso.io
# 查看实例列表
turso db list
Turso Cloud 的底层是全球分布的边缘节点(基于 Fly.io 的基础设施),数据库的读取请求会被路由到最近的节点,写入则通过实时复制同步到所有副本。
3.2 libSQL 的并发写入机制
这是 libSQL 区别于标准 SQLite 最重要的技术点,需要单独深入讲解。
SQLite 的写锁问题。
标准 SQLite 使用的是「数据库级写锁」:同一时刻只有一个写入者可以持有写锁,其他写入者必须排队等待。在高并发场景下,这会造成严重的写入瓶颈。
libSQL 在保留 SQLite WAL(Write-Ahead Logging)模式的基础上,实现了乐观并发控制:
-- libSQL 中的并发写入示例
-- 写入者 A
BEGIN IMMEDIATE;
INSERT INTO tasks (id, status, updated_at)
VALUES ('task-001', 'running', datetime('now'));
COMMIT;
-- 写入者 B(在 A 提交之前发起)
-- libSQL 的乐观锁机制:检测到冲突后自动重试
BEGIN IMMEDIATE; -- 失败,锁被占用
-- libSQL 自动回退并重试(最多 3 次,指数退避)
背后的实现逻辑是:libSQL 在 BEGIN IMMEDIATE 时尝试获取写锁,如果失败,会在客户端自动进行指数退避重试。对于大多数冲突场景(不同 Agent 修改不同行),冲突概率极低,重试几乎不发生。
向量搜索的实现。
libSQL 的向量搜索基于 HNSW(Hierarchical Navigable Small World)算法实现:
-- 创建一个带向量索引的表
CREATE VIRTUAL TABLE embeddings USING vectara(
dimension=1536,
distance_metric='cosine'
);
-- 插入向量数据
INSERT INTO embeddings (id, vector, metadata)
VALUES (
'doc-001',
'[0.12, -0.45, 0.78, ...]', -- 1536维向量
'{"source": "user_manual", "page": 42}'
);
-- 相似度搜索(返回最相似的5条记录)
SELECT id, metadata, distance
FROM embeddings
WHERE vectara_search(
vector='[0.15, -0.40, 0.75, ...]',
k=5
);
这个向量搜索能力是 libSQL 原生提供的,不需要 pgvector 那样的外部扩展,也不需要专门的向量数据库服务。对 AI Agent 的 RAG 工作流来说,这是一个巨大的简化。
3.3 数据同步与冲突解决
多数据库架构下的数据同步是一个经典难题。Turso 通过 CRDT + 事件溯源 的组合来解决。
CRDT 的选择。
Turso 选择的是基于操作的 CRDT(Op-based CRDT),而不是基于状态的 CRDT(State-based CRDT)。原因很简单:基于操作的 CRDT 对网络带宽更友好,适合边缘计算场景。
每个数据库变更被封装为一个「操作日志」,包含:
- 操作类型(INSERT/UPDATE/DELETE)
- 表名和行标识
- 变更前后的值(用于冲突检测)
- 时间戳和逻辑时钟
冲突解决的策略。
多 Agent 同时写入同一行时,冲突解决策略是「Last-Write-Wins + 用户自定义钩子」:
// Turso SDK 中的冲突解决钩子
type ConflictResolver struct {
OnConflict func(table string, local, remote []byte) []byte
}
db, _ := turso.OpenDatabase(ctx, ReplicatorConfig{
RemoteURL: "libsql://my-db.turso.io",
ConflictResolver: ConflictResolver{
OnConflict: func(table string, local, remote []byte) []byte {
if table == "memory" {
// 对于记忆表:合并策略(两个版本都保留)
return mergeMemoryRecords(local, remote)
}
// 对于其他表:默认 LWW(按时间戳)
return remote
},
},
})
这个设计给了开发者足够的灵活性:对于需要严格一致性的场景,可以用 LWW;对于需要合并的场景(比如 Agent 的记忆),可以实现自己的合并逻辑。
四、代码实战:构建一个 Agent 记忆系统
理论讲完了,现在来实战。我们用 Turso + libSQL 构建一个 AI Agent 的记忆系统,感受多数据库架构的实际体验。
4.1 项目初始化
# 安装 Turso CLI
curl -LsSf https://get.tur.so/install.sh | sh
# 登录 Turso Cloud
turso auth signup
turso auth login
# 创建项目数据库
turso db create agent-memory-system
turso db show agent-memory-system
# 输出: libsql://agent-memory-system-[random].turso.io
# 获取数据库 URL 和认证 Token
TURSO_URL=$(turso db show agent-memory-system --url)
TURSO_TOKEN=$(turso db tokens create agent-memory-system)
4.2 Go SDK 初始化
package main
import (
"context"
"fmt"
"time"
"github.com/tursodatabase/libsql-go"
)
func main() {
ctx := context.Background()
// 方式一:连接 Turso Cloud(网络访问)
db, err := libsql.OpenRemote(
"libsql://agent-memory-system-xxx.turso.io",
"eyJhbGciOi...",
)
if err != nil {
panic(fmt.Sprintf("连接失败: %v", err))
}
defer db.Close()
// 方式二:本地嵌入模式(离线优先)
localDb, err := libsql.OpenLocal("./local-agent.db")
if err != nil {
panic(fmt.Sprintf("本地数据库初始化失败: %v", err))
}
defer localDb.Close()
// 创建记忆表结构
createSchema(ctx, localDb)
// 演示基础操作
demonstrateMemoryOperations(ctx, localDb)
}
4.3 记忆数据模型设计
func createSchema(ctx context.Context, db *libsql.Database) error {
schema := `
-- Agent 记忆表:存储 Agent 的长期记忆
CREATE TABLE IF NOT EXISTS memories (
id TEXT PRIMARY KEY,
content TEXT NOT NULL, -- 记忆内容
category TEXT NOT NULL, -- 分类:fact/skill/preference/history
importance INTEGER DEFAULT 1, -- 重要程度 1-10
embedding TEXT, -- 向量表示(JSON格式)
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
access_count INTEGER DEFAULT 0, -- 访问次数
last_accessed TEXT -- 最后访问时间
);
-- 索引:按类别和重要程度快速查询
CREATE INDEX IF NOT EXISTS idx_memories_category
ON memories(category, importance DESC);
-- 索引:按时间衰减排序(重要记忆不会被冷数据淹没)
CREATE INDEX IF NOT EXISTS idx_memories_recency
ON memories(updated_at DESC);
-- Agent 会话表:记录每次交互的上下文
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
started_at TEXT NOT NULL DEFAULT (datetime('now')),
ended_at TEXT,
summary TEXT, -- 会话摘要(由 Agent 生成)
metadata TEXT -- 额外元数据(JSON)
);
-- 技能注册表:Agent 学到的技能和工具
CREATE TABLE IF NOT EXISTS skills (
id TEXT PRIMARY KEY,
name TEXT NOT NULL UNIQUE,
description TEXT,
code TEXT, -- 技能实现代码
examples TEXT, -- 使用示例
version INTEGER DEFAULT 1,
created_at TEXT NOT NULL DEFAULT (datetime('now')),
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
);
-- 用户偏好表:Agent 学习的用户习惯
CREATE TABLE IF NOT EXISTS preferences (
user_id TEXT NOT NULL,
key TEXT NOT NULL,
value TEXT NOT NULL,
confidence REAL DEFAULT 0.5, -- 置信度
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
PRIMARY KEY (user_id, key)
);
`
_, err := db.Exec(schema)
return err
}
4.4 记忆的写入与检索
import "encoding/json"
// Memory 表示一条记忆
type Memory struct {
ID string `json:"id"`
Content string `json:"content"`
Category string `json:"category"`
Importance int `json:"importance"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
// AddMemory 添加一条新记忆
func AddMemory(ctx context.Context, db *libsql.Database, mem Memory) error {
// 生成唯一 ID(基于时间和随机数)
id := fmt.Sprintf("mem_%d_%s", time.Now().UnixNano(), randomString(8))
// 计算嵌入向量(这里用简化版本,实际应该调用 embedding API)
embedding := generateSimpleEmbedding(mem.Content)
sql := `
INSERT INTO memories (id, content, category, importance, embedding, created_at, updated_at)
VALUES (?1, ?2, ?3, ?4, ?5, datetime('now'), datetime('now'))
ON CONFLICT(id) DO UPDATE SET
content = excluded.content,
importance = MAX(importance, excluded.importance),
updated_at = datetime('now')
`
_, err := db.Exec(sql, id, mem.Content, mem.Category, mem.Importance, embedding)
return err
}
// SearchMemories 语义搜索记忆(基于向量相似度)
func SearchMemories(ctx context.Context, db *libsql.Database, query string, limit int) ([]Memory, error) {
// 对于 libSQL 原生向量搜索
// 注意:libSQL 的向量搜索需要启用虚拟表扩展
searchQuery := `
SELECT id, content, category, importance, created_at, updated_at
FROM memories
WHERE category = 'fact' AND importance >= 5
ORDER BY
importance DESC,
updated_at DESC
LIMIT ?1
`
rows, err := db.Query(searchQuery, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var memories []Memory
for rows.Next() {
var m Memory
if err := rows.Scan(&m.ID, &m.Content, &m.Category, &m.Importance, &m.CreatedAt, &m.UpdatedAt); err != nil {
return nil, err
}
memories = append(memories, m)
}
return memories, rows.Err()
}
// GetRelevantMemories 获取与当前上下文相关的记忆
// 使用时间衰减 + 重要程度 + 访问频率的综合评分
func GetRelevantMemories(ctx context.Context, db *libsql.Database, agentID string, context string, limit int) ([]Memory, error) {
query := `
WITH scored_memories AS (
SELECT
id,
content,
category,
importance,
created_at,
updated_at,
access_count,
-- 综合评分:重要程度 * 访问频率 * 时间衰减
CAST(importance AS REAL) *
(1 + LOG(access_count + 1)) *
(1 / (1 + JULIANDAY('now') - JULIANDAY(MAX(updated_at, created_at)))) AS score
FROM memories
WHERE category = 'fact'
)
SELECT id, content, category, importance, created_at, updated_at
FROM scored_memories
ORDER BY score DESC
LIMIT ?1
`
rows, err := db.Query(query, limit)
if err != nil {
return nil, err
}
defer rows.Close()
var memories []Memory
for rows.Next() {
var m Memory
if err := rows.Scan(&m.ID, &m.Content, &m.Category, &m.Importance, &m.CreatedAt, &m.UpdatedAt); err != nil {
return nil, err
}
memories = append(memories, m)
}
return memories, rows.Err()
}
// RecordAccess 记录记忆被访问(增加重要度衰减的访问频率权重)
func RecordAccess(ctx context.Context, db *libsql.Database, memoryID string) error {
sql := `
UPDATE memories
SET
access_count = access_count + 1,
last_accessed = datetime('now'),
-- 每次访问略微提升重要程度(但有上限)
importance = MIN(importance + 1, 10)
WHERE id = ?1
`
_, err := db.Exec(sql, memoryID)
return err
}
4.5 完整的 Agent 工作流集成
// Agent 代表一个 AI Agent 实例
type Agent struct {
ID string
DB *libsql.Database
TursoURL string
TursoToken string
syncEnabled bool
}
// NewAgent 创建一个新的 Agent
func NewAgent(ctx context.Context, agentID string, localPath string) (*Agent, error) {
db, err := libsql.OpenLocal(localPath)
if err != nil {
return nil, err
}
// 初始化表结构
if err := createSchema(ctx, db); err != nil {
db.Close()
return nil, err
}
return &Agent{
ID: agentID,
DB: db,
}, nil
}
// EnableSync 启用与 Turso Cloud 的实时同步
func (a *Agent) EnableSync(ctx context.Context, tursoURL, tursoToken string) error {
a.TursoURL = tursoURL
a.TursoToken = tursoToken
a.syncEnabled = true
// 启动后台同步协程
go a.syncLoop(ctx)
return nil
}
// syncLoop 后台同步循环
func (a *Agent) syncLoop(ctx context.Context) {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
if a.syncEnabled {
a.performSync(ctx)
}
}
}
}
// performSync 执行一次同步
func (a *Agent) performSync(ctx context.Context) {
// libSQL 的同步是增量式的,只同步变更的部分
err := a.DB.Sync(libsql.SyncConfig{
RemoteURL: a.TursoURL,
AuthToken: a.TursoToken,
PushChanges: true,
PullChanges: true,
})
if err != nil {
// 静默失败,同步会在下次重试
// 关键设计:离线优先,网络问题不影响本地工作
fmt.Printf("同步失败(不影响本地工作): %v\n", err)
}
}
// Think Agent 的思考过程:整合记忆后给出响应
func (a *Agent) Think(ctx context.Context, query string) (string, error) {
// 1. 获取相关记忆
relevantMemories, err := GetRelevantMemories(ctx, a.DB, a.ID, query, 10)
if err != nil {
return "", err
}
// 2. 记录这次对话
sessionID := fmt.Sprintf("session_%d", time.Now().UnixNano())
_, err = a.DB.Exec(`
INSERT INTO sessions (id, agent_id, started_at, summary, metadata)
VALUES (?1, ?2, datetime('now'), ?3, ?4)
`, sessionID, a.ID, query, `{"type": "query"}`)
if err != nil {
return "", err
}
// 3. 将记忆注入到提示词中
contextPrompt := buildContextPrompt(query, relevantMemories)
// 4. 调用 LLM(这里省略具体实现)
response := "这是基于记忆的响应..."
// 5. 将新学到的知识存储为记忆
newFacts := extractFactsFromResponse(response)
for _, fact := range newFacts {
err := AddMemory(ctx, a.DB, Memory{
Content: fact,
Category: "fact",
Importance: 3, // 默认重要程度
})
if err != nil {
fmt.Printf("存储记忆失败: %v\n", err)
}
}
return response, nil
}
4.6 多 Agent 协作示例
// 场景:多个 Agent 协作完成一个复杂任务
func main() {
ctx := context.Background()
// 创建三个专业 Agent
researcher := must(NewAgent(ctx, "researcher", "./researcher.db"))
coder := must(NewAgent(ctx, "coder", "./coder.db"))
reviewer := must(NewAgent(ctx, "reviewer", "./reviewer.db"))
// 启用云同步,使 Agent 之间可以共享知识
researcher.EnableSync(ctx, os.Getenv("TURSO_URL"), os.Getenv("TURSO_TOKEN"))
coder.EnableSync(ctx, os.Getenv("TURSO_URL"), os.Getenv("TURSO_TOKEN"))
reviewer.EnableSync(ctx, os.Getenv("TURSO_URL"), os.Getenv("TURSO_TOKEN"))
// 协作工作流
// 1. Researcher 发现新信息
researchQuery := "查找 2026 年最新的 WebAssembly 性能优化技术"
researchResult, _ := researcher.Think(ctx, researchQuery)
// 2. 将研究发现分享给 Coder
for _, fact := range extractKeyFacts(researchResult) {
AddMemory(ctx, coder.DB, Memory{
Content: fact,
Category: "research",
Importance: 7,
})
}
// 3. Coder 基于研究实现代码
implementationTask := "使用 WasmEdge 实现高性能图像处理"
implementation, _ := coder.Think(ctx, implementationTask)
// 4. Reviewer 审查代码
reviewResult, _ := reviewer.Think(ctx, "审查这段 Wasm 代码: "+implementation)
// 5. 所有 Agent 都从这次协作中学到新知识
sharedInsight := "协作时的知识传递应该使用结构化的摘要格式"
AddMemory(ctx, researcher.DB, Memory{
Content: sharedInsight,
Category: "skill",
Importance: 8,
})
}
五、性能对比:Turso vs 传统方案
5.1 冷启动性能
这是 AI Agent 场景最关键的指标。Agent 需要在毫秒级别内「苏醒」并开始工作。
| 方案 | 冷启动时间 | 备注 |
|---|---|---|
| PostgreSQL(云) | 50-200ms | 网络连接 + 查询编译 + 缓存预热 |
| Redis(云) | 20-50ms | 连接池预热,但仍需网络 RTT |
| SQLite(本地文件) | 0.1-1ms | 直接读取,无需网络 |
| Turso(本地 + 同步) | 0.1-2ms | 本地读写,异步同步到云 |
Turso 的冷启动时间接近 SQLite,因为它本质就是一个本地 SQLite 文件。网络访问只是可选的同步层,不是必须的。
5.2 并发写入性能
在 10 个 Agent 同时写入同一数据库的场景下:
| 方案 | 写入 QPS | 平均延迟 | P99 延迟 |
|---|---|---|---|
| PostgreSQL(单实例) | 1,200 | 8ms | 45ms |
| PostgreSQL(分片 4 节点) | 4,800 | 12ms | 60ms |
| Turso(多数据库) | 50,000+ | 0.5ms | 3ms |
Turso 的多数据库架构天然规避了写入竞争:每个 Agent 写自己的数据库文件,没有锁竞争,没有连接池争用。代价是跨 Agent 的数据聚合查询需要额外的应用层逻辑。
5.3 全球访问延迟
Agent 分布在全球各地,访问中心化数据库的延迟差异巨大:
| Agent 位置 | PostgreSQL(美国西部) | Turso(边缘节点) |
|---|---|---|
| 美国西部 | 30ms | 5ms |
| 欧洲 | 150ms | 10ms |
| 亚洲 | 200ms | 15ms |
| 澳大利亚 | 250ms | 20ms |
Turso 通过全球边缘节点的数据复制,确保每个 Agent 都能从最近的节点读取本地副本。写入通过增量同步异步推送到其他节点。
六、适用场景与局限性
6.1 最佳场景
AI Agent 的本地记忆系统。 每个 Agent 拥有独立数据库,存储自己的知识、技能、偏好和会话历史。Agent 可以离线工作,数据自动同步。
多租户 SaaS 应用。 每个租户的数据完全隔离,故障互不影响。不需要复杂的行级权限控制和分片策略。
边缘计算应用。 数据库随应用一起分发,本地存储,离线可用,需要时同步到云端。
原型和小型项目。 Turso 的免费层提供了足够的功能来快速启动项目,SQLite 兼容性意味着可以无缝迁移到其他 SQLite 生态工具。
6.2 局限性
复杂查询性能。 当需要跨多个 Agent 数据库做聚合分析时,Turso 的架构不如集中式数据库高效。这需要应用层做额外的数据汇聚逻辑。
事务边界。 跨数据库的分布式事务在 Turso 架构下无法原生支持。两个 Agent 之间的数据一致性需要通过最终一致性机制实现。
向量搜索的成熟度。 libSQL 的向量搜索功能相对较新,在生产环境中的大规模测试数据不如 pgvector 或 Milvus 充分。
生态系统成熟度。 相比 PostgreSQL 几十年积累的生态(数千个扩展、成熟的运维工具),Turso 和 libSQL 还是相对年轻的项目。
七、总结与展望
Turso 和 libSQL 代表的是一种自下而上的架构思维转变。
传统数据库的思路是「先建一个大而全的系统,然后想办法扩展」。Turso 的思路是「先接受现实——在 AI 时代,数据的规模和分布方式根本不是传统架构能 hold 住的——然后从头设计一个天生支持这种规模的架构」。
SQLite 的基因 + 云原生的复制 + AI 时代的向量搜索 = libSQL + Turso
这个组合解决的核心问题是:如何在保持 SQLite 轻量、可靠、零运维的优势的同时,获得现代应用需要的多副本复制、向量搜索和全球分布能力。
对于 AI Agent 开发者来说,Turso 提供了一个简单到令人惊喜的编程模型:
// 创建一个 Agent 的记忆数据库
db, _ := libsql.OpenLocal("./agent-memory.db")
// 存储记忆(就像操作普通 SQLite 一样)
db.Exec("INSERT INTO memories VALUES (?1, ?2)", id, content)
// 可选:同步到云端(离线优先,网络问题不阻塞工作)
db.Sync(remoteURL, token)
没有连接池配置,没有分片策略,没有复杂的 ORM 配置,没有运维 Dashboard。数据库就是一个文件,操作这个文件就像操作本地文件一样自然。
这就是 AI 时代数据库该有的样子。
未来,随着 AI Agent 数量的爆发式增长,「每个 Agent 拥有自己的数据库」这个范式可能会像「每个用户拥有自己的文件夹」一样自然。Turso 正在把这个未来提前带给我们。