Turso React Native SDK 完全指南:在移动端构建可离线同步的嵌入式副本数据库
【免费下载链接】tursoA SQL database in Rust: SQLite-compatible, now also speaking Postgres (experimental). The LLVM of databases.项目地址: https://gitcode.com/GitHub_Trending/tu/turso
导读
本文围绕 bindings/react-native/README.md 展开,完整讲解 Turso React Native 绑定(@tursodatabase/sync-react-native)的安装、配置与使用:它允许你的 iOS / Android 应用在本地以 SQLite 兼容的嵌入式副本(embedded replica)方式运行数据库,并在有网络时与 Turso 云端数据库双向同步。读完本文,你将掌握本地数据库、云同步数据库、加密远程库的完整接入方案,以及 SDK 的底层架构(JSI 桥接、异步 IO 处理)原理。
Turso 本身是一个用 Rust 编写的 SQL 数据库引擎,兼容 SQLite,并新增了同步引擎能力。本 SDK 把这一能力桥接进 React Native:核心逻辑位于 TypeScript 与 Rust 中,C++ 层只是一个薄薄的 JSI 桥接层。
1. 安装与平台配置
1.1 安装 npm 包
npm install @tursodatabase/sync-react-native从仓库的 bindings/react-native/package.json 可以看到该包的元信息:主入口为lib/commonjs/index.js(构建产物由react-native-builder-bob生成),TypeScript 类型定义位于lib/typescript/index.d.ts,源码位于src/index.ts。它要求react >= 18.0.0、react-native >= 0.76.0(peerDependencies),运行环境 Node 需>= 18。
1.2 iOS:pod install
cd ios && pod installiOS 依赖一个预编译的 Rust XCFramework(turso-sync-sdk-kit.xcframework)。CocoaPods 配置见 bindings/react-native/turso-sync-react-native.podspec:
- 平台要求
ios >= 13.0; - 以
vendored_frameworks方式引入 Rust 构建产物,设备与模拟器架构自动切换; - 内置
script_phase,若libs/ios/turso-sync-sdk-kit.xcframework不存在,会先执行make ios编译 Rust 库(C++ 标准c++20,链接-lc++)。
如果你需要从源码重新构建 Rust 原生库,可参考 bindings/react-native/Makefile:make ios会通过rustup target add添加aarch64-apple-ios与aarch64-apple-ios-sim目标后执行cargo build --release;make android则交叉编译aarch64-linux-android、armv7-linux-androideabi、x86_64-linux-android、i686-linux-android四个 ABI 的.so文件。
1.3 Android:minSdkVersion
Android 侧要求minSdkVersion不低于21,在android/build.gradle中配置。原生桥接模块实现位于 bindings/react-native/android/src/main/java/com/turso/sync/reactnative/TursoModule.java:
- 通过
System.loadLibrary("turso_sync_sdk_kit")加载 Rust 动态库; - 通过
getConstants()暴露ANDROID_DATABASE_PATH(应用的数据库目录)、ANDROID_FILES_PATH、ANDROID_EXTERNAL_FILES_PATH等常量; - 暴露
install()同步方法,把 JSI 桥接安装到 JS 运行时。
iOS 侧对应实现见 bindings/react-native/ios/TursoModule.mm:它读取应用 Documents 目录(若配置了Turso_AppGroup,则使用 App Group 容器路径,便于 App 与扩展共享数据),并通过turso::install(*runtime, callInvoker, ...)安装 JSI 模块。
注意:SDK 依赖 React Native 的New Architecture(新架构),
src/index.ts在模块加载时会检查原生模块与__TursoProxy全局对象,若 JSI 绑定安装失败会直接抛错提示。
2. 快速开始:同步数据库
import { Database, getDbPath } from '@tursodatabase/sync-react-native'; // 获取平台可写路径 const dbPath = getDbPath('myapp.db'); // 创建带同步功能的数据库 const db = new Database({ path: dbPath, url: 'libsql://your-db.turso.io', authToken: 'your-auth-token', }); // 连接(若本地为空则从远端引导初始化) await db.connect(); // 查询本地副本(快速) const users = await db.all('SELECT * FROM users'); // 本地写入 await db.run('INSERT INTO users (name) VALUES (?)', ['Alice']); // 与远端同步 await db.push(); // 推送本地变更 await db.pull(); // 拉取远端变更 // 用完关闭 await db.close();关键点说明:
getDbPath(filename):返回平台特定的可写目录下的绝对路径。iOS 为 Documents 目录,Android 为数据库目录(见 src/index.ts 与paths.databasegetter)。connect():本地库直接打开;同步库则会执行create()(bootstrap)并建立连接(见 src/Database.ts)。url是判据:Database构造函数通过isSyncConfig(opts)判断——只要url非空,即进入同步模式(见 src/Database.ts)。- 你还可以使用便捷函数
connect(opts),它会new Database(opts)并立即connect()后返回实例(见 src/index.ts)。
3. 纯本地数据库(Local-Only Database)
不传url即为纯本地数据库,无需网络、无需鉴权:
const db = new Database({ path: getDbPath('local.db') }); await db.connect(); await db.exec('CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT)'); await db.run('INSERT INTO users (name) VALUES (?)', ['Bob']); const user = await db.get('SELECT * FROM users WHERE id = ?', [1]); await db.close();本地模式在原生层以阻塞 IO打开(async_io: false),而同步模式使用异步 IO(async_io: true),因为同步引擎需要外部网络 IO 循环配合(见 src/Database.ts)。所有数据库操作均为异步 API,统一了本地与同步两种场景的调用方式。
另外,路径可以是相对路径(自动放入可写目录)、绝对路径,甚至是:memory:内存数据库(见 src/index.ts 中的connect文档注释)。
4. 加密远程数据库(Encrypted Remote Database)
当云端数据库启用了加密时,通过remoteEncryption传入加密配置:
const db = new Database({ path: getDbPath('encrypted.db'), url: 'libsql://your-db.turso.io', authToken: 'your-auth-token', remoteEncryption: { cipher: 'aes256gcm', key: 'base64-encoded-key', }, });加密参数详解(定义见 src/types.ts):
| cipher 取值 | 密钥要求 | reservedBytes(保留字节数) |
|---|---|---|
aes256gcm/aes128gcm/chacha20poly1305 | base64 编码,16 或 32 字节(视 cipher) | 28 |
aegis128l/aegis128x2/aegis128x4 | base64 编码 | 32 |
aegis256/aegis256x2/aegis256x4 | base64 编码 | 48 |
Database内部通过getReservedBytesForCipher()根据 cipher 计算保留字节数并传入同步引擎(见 src/Database.ts),这些保留字节数与 Turso Cloud 的加密设置保持一致。同步引擎会收到remoteEncryptionKey与remoteEncryptionCipher,密钥用于构造 HTTP 请求头。
5. API 参考
5.1 Database 方法
| 方法 | 说明 |
|---|---|
connect() | 打开 / 引导初始化数据库 |
exec(sql) | 执行 SQL(无返回结果,支持多条语句) |
run(sql, params?) | 执行 SQL,返回{ changes, lastInsertRowid } |
get(sql, params?) | 查询单行 |
all(sql, params?) | 查询所有行 |
prepare(sql) | 创建预编译语句(返回Statement) |
close() | 关闭数据库 |
5.2 同步方法(提供url时可用)
| 方法 | 说明 |
|---|---|
push() | 推送本地变更到远端 |
pull() | 拉取远端变更到本地(有变更返回true,无变更返回false) |
sync() | 先 push 再 pull |
stats() | 获取同步统计信息 |
说明:
sync()在当前仓库的Database类中体现为push()与pull()的组合使用(文档 API 表中列出,源码中push()/pull()分别对应原生pushChanges()与waitChanges()+applyChanges()两个阶段,见 src/Database.ts)。同步库还额外提供checkpoint()用于触发检查点。
5.3 同步统计(stats()返回值)
SyncStats结构定义见 src/types.ts:
| 字段 | 含义 |
|---|---|
cdcOperations | CDC(变更数据捕获)操作数 |
mainWalSize | 主 WAL 大小 |
revertWalSize | 回滚 WAL 大小 |
lastPullUnixTime | 最近一次拉取时间(Unix 时间戳) |
lastPushUnixTime | 最近一次推送时间 |
networkSentBytes | 网络发送字节数 |
networkReceivedBytes | 网络接收字节数 |
revision | 远端版本号(字符串或null) |
5.4 事务(Transactions)
await db.transaction(async () => { await db.run('INSERT INTO users (name) VALUES (?)', ['Alice']); await db.run('INSERT INTO users (name) VALUES (?)', ['Bob']); // 成功则提交,出错则回滚 });transaction<T>(fn)的实现非常直观(见 src/Database.ts):先exec('BEGIN'),回调成功则exec('COMMIT'),抛出异常则exec('ROLLBACK')并重新抛出错误。此外还提供了inTransactiongetter(内部通过connection.getAutocommit()判断)与lastInsertRowidgetter 便于事务内取最近插入行 ID。
5.5 预编译语句(Statement)
prepare(sql)返回Statement,支持链式bind()、run()、get()、all()、reset()、finalize()。参数绑定支持三种形态(见 src/Statement.ts):
- 位置参数数组:
stmt.run(1, 'Alice')或stmt.run([1, 'Alice']); - 命名参数对象:
stmt.run({ $id: 1 })(内部通过namedPosition(name)解析占位符位置); - 单个标量值:
stmt.run(42)。
值类型映射(见 src/Statement.ts):null/undefined→ NULL,整数number→ INTEGER,浮点number→ REAL,string→ TEXT,ArrayBuffer/ TypedArray → BLOB。查询结果统一按列名组织为Row(Record<string, SQLiteValue>),其中SQLiteValue = null | number | string | ArrayBuffer。
6. 高级配置参数(DatabaseOpts 全解)
除path、url、authToken、remoteEncryption之外,DatabaseOpts还支持以下配置(完整定义见 src/types.ts):
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
clientName | string | 'turso-sync-react-native' | 客户端标识,SDK 会追加唯一后缀保证clientId唯一 |
longPollTimeoutMs | number | 不设则无超时 | 拉取操作的长轮询超时 |
bootstrapIfEmpty | boolean | true | 本地为空时是否从远端引导初始化;设为false则客户端仅在联网时才能连接全新数据库 |
pushOperationsThreshold | number | 不设则一次推送全部变更 | 单个 push HTTP 批次中 CDC 操作数上限,达到后按事务边界拆分(单个用户事务永不被拆散) |
pullBytesThreshold | number | 不设则单次往返完成 bootstrap | bootstrap 下载按字节拆分多个/pull-updates请求;对query引导策略无效 |
logicalMvccPull | boolean | false | 强制增量拉取使用 MVCC 逻辑日志流;默认自动探测远端协议并持久化,仅在需要时作为逃生舱口开启 |
partialSyncExperimental | object | 未启用 | 实验性局部同步(见下) |
6.1 实验性局部同步(partialSyncExperimental)
const db = new Database({ path: getDbPath('partial.db'), url: 'libsql://your-db.turso.io', authToken: 'your-auth-token', partialSyncExperimental: { // 前缀策略:启动时仅本地加载前 N 字节 bootstrapStrategy: { kind: 'prefix', length: 1024 * 1024 }, // 或查询策略:仅加载指定 SQL 触及的页面 // bootstrapStrategy: { kind: 'query', query: 'SELECT * FROM users' }, segmentSize: 128 * 1024, // 按段加载,128KB 约 32 页 prefetch: true, // 预取可能即将访问的页面 }, });三种引导策略说明(见 src/types.ts):
prefix:启动时仅下载数据库文件前 N 字节;query:仅下载指定 SQL 语句访问过的页面;segmentSize:让同步引擎按段批量加载页面(如 128KB 段即加载约 32 页);prefetch:预取未来可能访问的页面。
当局部同步遇到缺失页面时,语句执行会返回TursoStatus.IO,SDK 通过drainSyncIo()驱动同步引擎的 IO 队列补页后继续执行(见 src/Statement.ts 中的executeWithIo/stepWithIo循环,以及 src/internal/ioProcessor.ts)。
7. 底层架构解析:TypeScript 驱动、C++ 薄桥、Rust 引擎
理解 SDK 的分层有助于排查问题与评估性能:
┌─────────────────────────────────────────────┐ │ TypeScript 层(Database / Statement / │ │ asyncOperation / ioProcessor) │ ├─────────────────────────────────────────────┤ │ JSI 桥接层(C++:TursoHostObject、 │ │ TursoDatabaseHostObject、TursoSync...) │ ├─────────────────────────────────────────────┤ │ 原生模块(iOS: TursoModule.mm / │ │ Android: TursoModule.java) │ ├─────────────────────────────────────────────┤ │ Rust 引擎(sdk-kit + sync/sdk-kit, │ │ 以 .xcframework / .so 形式内置) │ └─────────────────────────────────────────────┘架构要点:
JSI 直连,无 JSON 序列化:原生层通过 JSI(JavaScript Interface)把
__TursoProxy注入全局对象(见 src/index.ts),TypeScript 直接调用原生方法,避免传统 Bridge 的序列化开销。原生侧 Host Object 源码位于 bindings/react-native/cpp/(TursoHostObject.cpp、TursoDatabaseHostObject.cpp、TursoConnectionHostObject.cpp、TursoStatementHostObject.cpp、TursoSyncDatabaseHostObject.cpp等)。异步 IO 全部由 JavaScript 驱动:同步引擎产生三类 IO 请求(见 src/internal/ioProcessor.ts 与
NativeSyncIoItem的getKind()):- HTTP:使用 React Native 标准
fetch()发出,URL 会从libsql:///turso://规范化为https://,并自动注入Authorization: Bearer <token>头; - FULL_READ / FULL_WRITE:整库文件的原子读写,默认走内置 JSI 文件系统函数;
- NONE:空操作。
这一设计的好处是:网络请求在 RN 调试器中可见、可自定义 fetch 行为(如代理、自定义头)、可 mock 测试、使用平台原生网络栈而非 C++ HTTP 库。
- HTTP:使用 React Native 标准
异步操作驱动循环:同步操作(
create、connect、pushChanges、waitChanges、applyChanges、checkpoint、stats)返回NativeSyncOperation,由 src/internal/asyncOperation.ts 的driveOperation()循环调用resume():状态为TursoStatus.IO时先处理 IO 队列再继续,TursoStatus.DONE时按resultKind提取连接 / 变更 / 统计结果。并发安全:
Database内部持有一个AsyncLock,所有语句执行(run/get/all/finalize)在锁内完成“绑定参数 → 执行 → 重置”,避免并发绑定/执行竞态;exec()则利用prepareFirst+tailIdx循环处理多语句 SQL。状态码体系:
TursoStatus枚举(src/types.ts)涵盖OK/DONE/ROW/IO/BUSY/INTERRUPT/ERROR/MISUSE/CONSTRAINT/READONLY/DATABASE_FULL/NOTADB/CORRUPT/IOERR等,TursoType枚举则对应 SQLite 值类型(INTEGER/REAL/TEXT/BLOB/NULL),用于结果行读取。可插拔文件系统:通过
setFileSystemImpl(readFile, writeFile)可覆盖内置文件读写实现(如加密、压缩等自定义需求),默认使用 JSI 内置函数(见 src/internal/ioProcessor.ts)。
8. 调试与日志
SDK 提供setup()用于配置引擎日志,应在任何数据库操作之前调用(见 src/index.ts):
import { setup } from '@tursodatabase/sync-react-native'; setup({ logLevel: 'debug', logger: (log) => { console.log(`[${log.level}] ${log.target}: ${log.message}`); }, });日志级别为'error' | 'warn' | 'info' | 'debug' | 'trace',每条日志包含message、target、file、line、timestamp、level字段(类型定义见 src/types.ts)。
9. 最佳实践与注意事项
- 离线优先(Offline-first):把
bootstrapIfEmpty设为false可避免网络不可用时对全新库的无谓 bootstrap 尝试;日常读写全部落在本地副本,响应快且离线可用。 - 路径管理:优先使用
getDbPath()或相对路径(SDK 自动归一化到可写目录);Android 上数据库目录为/data/data/<应用包名>/databases/,iOS 为 Documents 目录;同步库会在主文件旁生成-info、-wal等伴随文件。 - 善用
stats():通过cdcOperations、networkSentBytes、networkReceivedBytes等指标监控同步负载与网络消耗。 - 局部同步是实验特性:仅当数据库体积较大、需要控制启动下载量时才启用
partialSyncExperimental,并理解其“按需补页”的 IO 行为。 - 事务边界:
pushOperationsThreshold会按事务边界拆分推送批次,单个用户事务不会被拆散——这保证了远端回放的一致性语义。 - 版本与平台约束:当前包版本为
0.8.0-pre.10(预发布);要求 RN 新架构(New Architecture)、iOS 13+、Android minSdk 21+;如需从源码构建原生库,参考 bindings/react-native/Makefile 的make ios/make android。
10. 继续深入仓库
- SDK 入口与类型: bindings/react-native/src/index.ts、bindings/react-native/src/types.ts
- 数据库与语句实现: bindings/react-native/src/Database.ts、bindings/react-native/src/Statement.ts
- 异步 IO 与操作驱动: bindings/react-native/src/internal/ioProcessor.ts、bindings/react-native/src/internal/asyncOperation.ts
- 原生桥接: bindings/react-native/ios/TursoModule.mm、bindings/react-native/android/src/main/java/com/turso/sync/reactnative/TursoModule.java、bindings/react-native/cpp/
- Rust 引擎底层: sync/engine/、sync/sdk-kit/、sdk-kit/
- 完整示例工程: examples/react-native/
【免费下载链接】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),仅供参考