ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Turso Cloud 远程数据库实战:用 `@tursodatabase/serverless` 在 JavaScript 中读写云端 SQLite

Turso Cloud 远程数据库实战:用 `@tursodatabase/serverless` 在 JavaScript 中读写云端 SQLite Turso Cloud 远程数据库实战用tursodatabase/serverless在 JavaScript 中读写云端 SQLite【免费下载链接】tursoA SQL database in Rust: SQLite-compatible, now also speaking Postgres (experimental). The LLVM of databases.项目地址: https://gitcode.com/GitHub_Trending/tu/turso导读本文以仓库 serverless/javascript/examples/remote 示例为主线讲解如何通过 Turso 官方 Serverless 驱动tursodatabase/serverless连接 Turso Cloud 托管的远程 SQLite 数据库完成建表、批量写入与多种查询。读完本文你将掌握connect连接建立、batch原子写入、prepare/get/all/iterate四种执行方式、连接并发模型与底层 SQL over HTTP 协议原理并能直接改造示例用于 Cloudflare Workers、Vercel Edge 等无服务器环境。一、示例定位最简的 Turso Cloud 接入方式serverless/javascript/examples/remote/目录是仓库中演示如何使用 Turso Cloud的入门级示例包含三个文件README.md安装与运行说明本文讲解对象index.mjs完整可运行的示例程序package.json依赖清单唯一运行时依赖是本地源码目录中的tursodatabase/serverless包。示例的运行目标非常聚焦连接一个远程 SQLite 数据库 → 批量插入数据 → 用多种方式查询结果。它不涉及本地嵌入式数据库或同步功能纯粹展示驱动面向 Turso Cloud 的远程模式。补充说明tursodatabase/serverless是一个只用fetch() 的 Serverless 数据库驱动专为 Turso Cloud 设计可从 Cloudflare Workers、Vercel 等 Serverless 和边缘函数中连接数据库见 serverless/javascript/README.md 的 About 一节。由于只依赖 Web 标准fetch它可以在没有 Node.js 原生模块的运行环境中工作。二、准备 Turso Cloud 数据库与认证信息运行示例前你需要一个 Turso Cloud 数据库并准备好两个环境变量环境变量含义取值示例TURSO_DATABASE_URL数据库连接地址libsql://your-db.turso.ioTURSO_AUTH_TOKEN数据库访问令牌eyJhbGciOi...Turso 控制台生成TURSO_AUTH_TOKEN在本地开发调试时是可选的驱动源码中注释为 Authentication token (optional for local development with turso dev)见 session.ts但访问 Turso Cloud 远程数据库时必须提供。值得一提的细节驱动在内部会把libsql://或turso://前缀的 URL 自动改写为https://并去掉尾部斜杠因为协议端点路径需要以斜杠拼接。对应实现位于 session.ts 的normalizeUrl函数// Rewrite libsql:// and turso:// URLs to https:// and strip any trailing // slashes, since endpoint paths are appended with a leading slash. function normalizeUrl(url: string): string { return url.replace(/^(libsql|turso):\/\//, https://).replace(/\/$/, ); }三、安装依赖在serverless/javascript/examples/remote/目录下执行npm i根据 package.json其依赖通过tursodatabase/serverless: ../..指向仓库内的驱动源码因此本地安装即可直接引用最新实现无需发布到 npm 的版本。四、运行示例TURSO_DATABASE_URL... TURSO_AUTH_TOKEN... node index.mjs将两个环境变量替换为第二步中准备的值。程序会依次完成连接远程数据库 → 建表并批量插入三条数据 → 用all、prepareget、prepareall、prepareiterate四种方式查询并打印结果。五、示例代码逐段解析5.1 建立连接import { connect } from tursodatabase/serverless; const client connect({ url: process.env.TURSO_DATABASE_URL, authToken: process.env.TURSO_AUTH_TOKEN, });connect(config)是驱动入口导出自 index.ts。从源码看connect是一个轻量操作它只分配一个配置对象并构造Connection实例不会发起任何网络 I/O真正的请求发生在第一次查询时底层fetch()运行时会自动对同一 origin 复用 TCP/TLS 连接因此创建多个连接的成本很低见 connection.ts 中connect函数的文档注释。5.2 用batch原子批量写入await client.batch( [ CREATE TABLE IF NOT EXISTS users (email TEXT), INSERT INTO users VALUES (firstexample.com), INSERT INTO users VALUES (secondexample.com), INSERT INTO users VALUES (thirdexample.com), ], write, );batch的第二个参数write是批量执行模式驱动会将整批语句包装进BEGIN IMMEDIATE ... COMMIT的原子事务中。对照 session.ts 的normalizeBatchMode实现模式映射如下传入模式实际生成的 BEGIN 语句语义writeBEGIN IMMEDIATE写事务立即获取写锁read/deferredBEGIN DEFERRED读事务首次读写时才加锁immediateBEGIN IMMEDIATE立即加写锁exclusiveBEGIN EXCLUSIVE排他锁阻塞其他读写concurrentBEGIN CONCURRENTTurso 并发写模式从 connection.ts 的batch实现可知原子批处理在服务端构造为一条BEGIN mode→ 逐条用户语句每条都 gated 在前一条成功之上→COMMIT→ROLLBACK仅在 BEGIN 成功且 COMMIT 未成功时执行的步骤链整个批量过程只有一次 HTTP 往返遇到失败即停止并自动回滚。因此传入原子模式的batch时语句数组内不允许出现BEGIN、COMMIT、END、ROLLBACK、SAVEPOINT、RELEASE等事务控制语句否则驱动会在发送前拒绝TRANSACTION_CONTROL_KEYWORDS检查。不带模式调用batch时每条语句在各自的自增提交autocommit步骤中执行中途失败时前面已成功的语句保持已提交状态失败的DatabaseError会携带batchIndex失败语句的从零下标和batchResults每条语句的结果未执行的为null。5.3 连接级快捷查询all// Using the connection-level all method const users await client.all(SELECT * FROM users); console.log(Users (all):, users);Connection.all(sql, ...bindParameters)相当于prepare(sql).all(args)但只做一次往返——跳过describe阶段直接执行并返回所有行见 connection.ts。返回的每一行都是类数组 具名属性的双模式对象既可以用user[0]按下标访问也可以用user.email按列名访问createRowObject会把合法的列名以不可枚举属性的方式挂到数组上见 session.ts。5.4 预编译语句prepareget/all/iterate// Using prepare and get method const stmt client.prepare(SELECT * FROM users LIMIT 1); const firstUser await stmt.get(); console.log(First user:, firstUser); // Using prepare and all method const allUsers await stmt.all(); console.log(All users (all):, allUsers); // Using prepare and iterate method console.log(Users (iterate):); const iterateStmt client.prepare(SELECT * FROM users); for await (const user of iterateStmt.iterate()) { console.log( -, user[0]); }prepare会通过协议的describe请求获取列元数据stmt.columns()可查看四种执行方式的分工见 statement.ts方法返回适用场景stmt.get(args?)第一行无结果返回undefined按主键取单行stmt.all(args?)全部行的数组结果集不大、需整体处理stmt.iterate(args?)异步迭代器逐行yield大结果集、流式逐条处理、内存友好stmt.run(args?){ changes, lastInsertRowid }INSERT/UPDATE/DELETE 等写操作prepare支持位置参数与命名参数两种绑定方式const byId await client.prepare(SELECT * FROM users WHERE id ?); const row await byId.get([1]); // 位置参数 const byName await client.prepare(SELECT * FROM users WHERE name :name); const row2 await byName.get({ name: Alice }); // 命名参数iterate()针对共享连接会话的预编译语句会先缓冲结果再逐行产出避免在yield点持有连接锁导致嵌套查询死锁见 statement.ts 中iterate的实现注释。六、底层原理SQL over HTTP 协议与 baton示例看起来只是几个await调用但其背后是一套完整的SQL over HTTP流式协议理解它有助于合理设计并发代码。每个Session维护一个baton接力棒状态服务端会为每个会话保持一个打开的执行流客户端的每个请求携带上一次响应的baton来续接服务端状态响应再返回新的baton见 session.ts 的Session类。因此单个连接是单流single-stream的——同一时刻只能执行一条语句Connection内部通过AsyncLock自动串行化并发调用后到的调用会等待前一个完成。这与 SQLite 本身每个连接同一时刻一次执行的模型一致见 connection.ts 的并发模型文档。需要并行时创建多个连接。由于connect()不触发网络请求、底层fetch复用连接多连接的开销很小const config { url: process.env.TURSO_DATABASE_URL, authToken: process.env.TURSO_AUTH_TOKEN }; // 方式一每个并行查询一个连接 const [users, orders] await Promise.all([ connect(config).all(SELECT * FROM users WHERE active 1), connect(config).all(SELECT * FROM orders WHERE status pending), ]); // 方式二固定大小的连接池反复复用 const pool Array.from({ length: 4 }, () connect(config)); const results await Promise.all( queries.map((sql, i) pool[i % pool.length].all(sql)) );驱动在每次管线pipeline请求中都会附带一个get_autocommit探测据此在客户端缓存真实的事务状态conn.inTransaction与原生绑定中sqlite3_get_autocommit()的语义一致——包括通过裸BEGIN手动开启的事务也能正确反映见 session.ts 的inTransaction说明。协议细节可查阅 serverless/PROTOCOL.md。七、连接配置项速查除了示例中用到的url和authTokenconnect的配置对象还支持以下选项定义见 session.ts 的SessionConfig接口配置项类型说明urlstring数据库 URL必填authTokenstring认证令牌访问 Turso Cloud 必需remoteEncryptionKeystring远程加密数据库的 Base64 编码密钥用于访问启用了加密的 Turso Cloud 数据库defaultQueryTimeoutnumber默认最大查询执行毫秒数超时中断驱动内部用AbortSignal.timeout实现requestHeadersRecordstring, string附加到每个请求的额外 HTTP 头在标准头之后应用因此可以覆盖如Authorization设置Host键会抛错fetch 禁止其中requestHeaders还可按查询传入尾随参数{ requestHeaders: {...} }实现单次调用的头部覆盖连接级头部与查询级头部会做合并。若要让事务的BEGIN/COMMIT也携带自定义头应在连接级设置或使用原子batch整个事务就是一次 HTTP 请求。八、面向既有 libSQL 代码的兼容层remote-compat 示例如果你已有使用 libSQL 客户端 API 的存量代码仓库还提供了remote-compat示例README、index.mjs它演示通过兼容层以createClientexecute的 libSQL 风格访问同一个远程库import { createClient } from tursodatabase/serverless/compat; const client createClient({ url: process.env.TURSO_DATABASE_URL, authToken: process.env.TURSO_AUTH_TOKEN, }); await client.batch([ CREATE TABLE IF NOT EXISTS users (email TEXT), INSERT INTO users VALUES (firstexample.com), ... ], write); const result await client.execute(SELECT * FROM users); console.log(Users:, result.rows);兼容层位于 compat.ts它复刻了 libSQL 客户端的Config、ResultSet、Row可同时按数组下标与列名访问、TransactionModewrite/read/deferred/immediate/exclusive/concurrent等类型与语义让 libSQL 调用方几乎零改动迁移到 Serverless 驱动。九、加密数据库接入cloud-encryption 示例若 Turso Cloud 数据库启用了加密示例 cloud-encryption/README.md 给出了额外的环境变量与参数npm i export TURSO_DATABASE_URLlibsql://your-db.turso.io export TURSO_AUTH_TOKENyour-auth-token export TURSO_REMOTE_ENCRYPTION_KEYbase64-encoded-key node index.mjs对应到驱动配置即为const client connect({ url: process.env.TURSO_DATABASE_URL, authToken: process.env.TURSO_AUTH_TOKEN, remoteEncryptionKey: process.env.TURSO_REMOTE_ENCRYPTION_KEY, });remoteEncryptionKey在协议层通过专用请求头驱动导出的ENCRYPTION_KEY_HEADER见 protocol.ts传递给服务端解密密钥本身不落盘。加密能力对应的服务端存储实现可进一步参考 core/storage/encryption.rs。十、从示例到生产下一步建议并行与池化牢记单连接单流按第七节的多连接模式组织并发原子性选择需要全有或全无的写入用带mode的batch仅需顺序执行则省略模式以减少事务开销事务场景conn.transaction(...)在连接流上执行BEGIN/COMMIT/ROLLBACKconn.transactionAsync(...)则为每次事务开辟独立的服务端流不阻塞连接上的其他语句但回调内所有 SQL 必须通过事务句柄执行且连接上的会话级状态如PRAGMA设置不会带入新会话见 connection.ts更多用例仓库examples/javascript/下还有sync-node、database-wasm-vite、concurrent-writes等完整示例JavaScript 驱动 API 的完整说明见 docs/javascript-api-reference.md。从 examples/remote/index.mjs 这段不到四十行的代码出发配合本文对驱动源码层协议、并发模型与配置项的拆解你已经可以在任意支持fetch的 Serverless 平台上稳定地读写 Turso Cloud 的远程 SQLite 数据库。【免费下载链接】tursoA SQL database in Rust: SQLite-compatible, now also speaking Postgres (experimental). The LLVM of databases.项目地址: https://gitcode.com/GitHub_Trending/tu/turso创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表