当前位置: 首页 > 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.lryc.cn/news/625361.html

相关文章:

  • 极品飞车21:热度(NFS Heat)
  • React native Navigation 详解
  • 2020年EAAI SCI1区TOP,基于ORPFOA算法的多无人机在线变化任务路径规划,深度解析+性能实测
  • 跟踪不稳定目标:基于外观引导的运动建模实现无人机视频中的鲁棒多目标跟踪
  • 面试题储备-MQ篇 2-说说你对RocketMQ的理解
  • 智慧养老中IPTV融合对讲:重塑养老沟通新生态
  • 【Qt开发】常用控件(五)
  • 金融行业私域运营:企业微信+AI如何实现数智化经营?
  • LeetCode-17day:贪心算法
  • 云计算核心技术之云存储技术
  • C语言基础:(十九)数据在内存中的存储
  • MoonBit Perals Vol.06: Moonbit 与 LLVM 共舞 (上):编译前端实现
  • consul-基础概念
  • 一个多功能的文件分享工具--zdir手动部署教程
  • Tesollo DeltoGripper DG-5F具有抓握和操纵能力的灵巧手
  • Swift与C++混编深度解决方案:手动桥接 vs SwiftyCPP框架性能终极评测
  • 垂直领域大模型构建:法律行业“类ChatGPT”系统的训练与落地
  • 快手可灵招海外产品运营实习生
  • 亚矩阵云手机智能定位:助力Snapchat矩阵账号的本地化内容运营穿透技术
  • 【光学神经网络与人工智能应用专题】
  • 禾赛激光雷达AT128P/海康相机(2):基于欧几里德聚类的激光雷达障碍物检测
  • 【科研绘图系列】R语言绘制多种小提琴和云雨图
  • Kubernetes 简介
  • 初步学习WPF-Prism
  • 深入解析:Unity、Unreal Engine与Godot引擎中的Uniform变量管理
  • [ORACLE数据库] ORACLE 的 PL/SQL 块
  • 摄像头模块在运动相机中的应用
  • arcgis-提取范围中最大占比面积的信息或唯一值
  • 面试问题详解四:Qt 多线程与信号槽机制
  • Day09 Go语言深入学习(1)