当前位置: 首页 > news >正文

【Rust嵌入式键值对数据库redb】第一课 第一次写入

第一个程序:

use redb::{Database, TableDefinition, ReadableDatabase};const TABLE: TableDefinition<&str, u64> = TableDefinition::new("my_data");fn main() -> Result<(), Box<dyn std::error::Error>> {// 1) 创建或打开数据库文件let db = Database::create("target/demo.redb")?;// 2) 写事务let write_txn = db.begin_write()?;{let mut table = write_txn.open_table(TABLE)?;table.insert("alice", 1)?;table.insert("bob", 2)?;}write_txn.commit()?;// 3) 读事务let read_txn = db.begin_read()?; // 来自 ReadableDatabase traitlet table = read_txn.open_table(TABLE)?;if let Some(v) = table.get("alice")? {println!("alice = {}", v.value());}for item in table.range("a"..="z")? {let (k, v) = item?;println!("{} -> {}", k.value(), v.value());}Ok(())
}

输出:

alice = 1
alice -> 1
bob -> 2

redb是一个单写入多读取的数据库。用官方文档的话说:

Multiple reads may be performed concurrently, with each other, and with writes. Only a single write may be in progress at a time.

用Casey Rodarmor的话说:

(Result type vs mmap)
Nope, unfortunately not. The issue is that if the db file is being concurrently modified by another process, that would introduce undefined behavior. redb cannot detect this, so it must be unsafe, indicating that the caller must ensure that the db is not concurrently modified.

因此,程序员首先得确保同一时间仅开启一个写入线程。
当然,redb本身也做了一定得保证,比如在实验中至少发现以下两点:

1、Database::create会对于一个demo.redb进行上锁,再次对其运行Database::create则会报错:
Error: DatabaseAlreadyOpen
2、多个线程begin_write试图同时写时,会阻塞。以下面程序为例。

use redb::{Database, TableDefinition};
use std::sync::Arc;
use std::thread;
use std::time::Duration;const TABLE: TableDefinition<&str, u64> = TableDefinition::new("my_data");fn main() -> Result<(), Box<dyn std::error::Error>> {std::fs::create_dir_all("target")?;let db = Arc::new(Database::create(r"D:\git\redb\target\demo.redb")?);// 第一个写事务let db1 = Arc::clone(&db);let handle1 = thread::spawn(move || {let write_txn = db1.begin_write().expect("第一个写事务失败");println!("[线程1] 第一个写事务开始,睡 5 秒...");thread::sleep(Duration::from_secs(5));{let mut table = write_txn.open_table(TABLE).unwrap();table.insert("alice", 1).unwrap();}write_txn.commit().unwrap();println!("[线程1] 第一个写事务提交完成");});// 第二个写事务let db2 = Arc::clone(&db);let handle2 = thread::spawn(move || {println!("[线程2] 尝试开始第二个写事务...");let txn = db2.begin_write().expect("[线程2] 写事务失败");println!("[线程2] 第二个写事务获得锁,开始写入");{let mut table = txn.open_table(TABLE).unwrap();table.insert("bob", 2).unwrap();}txn.commit().unwrap();println!("[线程2] 第二个写事务提交完成");});handle1.join().unwrap();handle2.join().unwrap();Ok(())
}

结果如下

[线程1] 第一个写事务开始,睡 5 秒…
[线程2] 尝试开始第二个写事务…
[线程1] 第一个写事务提交完成
[线程2] 第二个写事务获得锁,开始写入
[线程2] 第二个写事务提交完成

至于上锁和阻塞是如何实现的,我们下节课继续

http://www.dtcms.com/a/338963.html

相关文章:

  • Matplotlib数据可视化实战:Matplotlib图表注释与美化入门
  • Kubernetes 的 YAML 配置文件-kind
  • 8.19作业
  • STM32 定时器(中断源)
  • Vibe 编码技巧与建议(Vibe Coding Tips and Tricks)
  • K近邻算法(knn)
  • SpringAIAlibaba之基础功能和基础类源码解析(2)
  • 添加右键菜单项以管理员权限打开 CMD
  • JUC之CompletableFuture【中】
  • [ORACLE数据库] ORACLE 的 PL/SQL 块
  • 开通会话内容存档获取聊天记录
  • 机器学习中的「损失函数」:模型优化的核心标尺
  • 源雀SCRM开源版企微客服功能重磅升级
  • Linux 正则表达式
  • 【新启航】航空飞机起落架深孔型腔的内轮廓检测方法探究 - 激光频率梳 3D 轮廓检测
  • JavaScript 性能优化:new Map vs Array.find() 查找速度深度对比
  • 机器翻译60天修炼专栏介绍和目录
  • C语言:字符函数与字符串函数(1)
  • 从 IP编码地址困局到网络优化:VLSM 与 CIDR 如何破解地址浪费与路由难题
  • 使用 Resilience4j 实现 Spring Boot 服务限流:轻量级容错的最佳实践
  • Java算法之排序
  • Bot 流量“假阳性”调优笔记
  • ListBoxes使得在专为灵活性和易用性设计
  • 消费者API
  • 云电脑 vs 传统PC:全面对比3A游戏与AI训练的成本与性能
  • Leetcode 3654. Minimum Sum After Divisible Sum Deletions
  • 【多模态大模型的三化】
  • [PV]AXI R/W/RW带宽计算的tcl脚本
  • AI赋能商业数据分析:从海量数据挖掘到智能决策洞察,激活企业增长新动能
  • Redisson 分布式锁核心机制解析