数据库的基本原则
数据库的核心原则
-
原子性与持久性:原子性(Atomicity)确保一个事务中的所有操作要么全部完成,要么完全不执行,不会出现部分完成的情况。持久性(Durability)则保证一旦事务提交成功,即使发生系统故障,数据的变化也是永久性的。为了实现持久性,可以使用
fsync来确保操作系统将数据实际写入到磁盘而不是仅仅保存在缓存中。当数据库崩溃时,需要有一种机制来进行恢复,确保数据的一致性和完整性。 -
基于B树的键值存储:这是一种常用的组织和存储数据的方式,特别适合于磁盘上的数据结构。B树是一种平衡树,允许搜索、顺序访问、插入和删除在一个对数时间内完成。通过使用自由列表(free list),可以有效地管理磁盘空间,从而提高性能和效率。
-
关系数据库建立在键值存储之上:在这个层次上,表和索引被映射到底层的B树结构。这允许数据库系统以一种高效的方式管理和查询数据。此外,这种类型的数据库通常支持类似SQL的查询语言,它包含了解析器和解释器来处理和优化查询请求。
-
事务的并发控制:在多用户环境中,多个事务可能同时尝试访问或修改相同的数据。因此,必须有机制来控制并发事务的执行,以防止数据不一致或其他问题。常见的并发控制技术包括锁定协议(如两阶段锁)、时间戳排序和乐观并发控制等。
理解数据库的核心原则而不是仅仅掌握术语确实是一个更加有效的方法来学习和构建数据库。以下是一些关键的原则,它们构成了数据库系统的基础,并且可以帮助你通过实践来学习如何构建一个简单的数据库。

通过实践学习:原则而非术语
数据库文献中充满了令人困惑且含义重叠的术语,阅读这些内容时很容易迷失方向。另一方面,费曼曾说过:“我不能构建的东西,我就不理解。” 那么,你能通过阅读有关数据库的内容来构建一个数据库吗?测试一下你的理解吧!
虽然有很多东西需要学习,但并非所有知识都同等重要。构建一个数据库只需要掌握几个基本的原则,因此任何人都可以尝试。
核心原则
-
数据模型:
- 数据库需要定义如何组织和存储数据。最基本的数据模型之一是键值对(Key-Value),它简单直观,非常适合初学者理解数据库的基本操作如插入、查找、更新和删除。
-
持久性与恢复:
- 数据库必须能够将数据持久化到非易失性存储介质中,例如硬盘。使用写前日志(Write-Ahead Logging, WAL)是一种常见技术,用于确保即使在系统崩溃的情况下也能恢复数据。
-
索引结构:
- 为了提高数据检索效率,数据库通常会使用索引。B树或其变体B+树是常见的索引结构,允许快速查找、插入和删除操作。
-
事务处理:
- 事务是指一组操作要么全部执行成功,要么完全不执行,从而保证了数据库的一致性和完整性。ACID特性(原子性、一致性、隔离性、持久性)是评估事务处理的重要标准。
-
并发控制:
- 当多个用户同时访问数据库时,必须有一种机制来管理这些访问,以避免数据不一致的问题。这可以通过锁机制或者更高级的多版本并发控制(MVCC)实现。
实践建议
-
动手实践:尝试从头开始编写一个简单的键值存储系统。首先实现基本的
PUT和GET功能,并考虑如何持久化这些数据。 -
逐步扩展:一旦有了基础的键值存储,可以考虑添加B树或其他索引来加速查找过程。然后,尝试实现简单的事务支持,比如如何确保在一个操作失败时能够回滚所有相关更改。
-
模拟故障:测试你的数据库在各种异常情况下的表现,例如突然断电或程序崩溃后能否正确恢复数据。
-
学习资源:虽然避免过多的专业术语很重要,但了解一些基础概念还是必要的。可以选择那些强调实际构建而非单纯理论讲解的学习材料或教程。
手机使用SQLite而非其他格式(如JSON)存储数据的原因在于,数据库系统提供了更高级的数据完整性和可靠性保证,尤其是在处理异常情况时。以下是关于为何选择SQLite以及如何通过一些技术手段实现数据的持久性和原子性的详细解释。
为什么选择SQLite而不是JSON?
- 数据完整性和一致性:如果直接使用文件格式(例如JSON),在写入过程中遭遇崩溃可能会导致数据丢失或损坏。这是因为写操作可能只完成了一部分,导致文件处于不一致的状态。
- 事务支持:SQLite等数据库管理系统(DBMS)提供事务支持,确保数据要么完全更新成功,要么完全不更新(原子性),同时保证一旦事务提交后数据不会丢失(持久性)。
如何通过技术手段解决这些问题
使用fsync实现持久性和原子性
-
持久性:指的是数据一旦被确认写入后,即使系统发生故障也不会丢失。在操作系统层面,写入操作并不总是立即将数据写入磁盘,而是先存储在缓存中。为了确保数据确实写到了磁盘上,可以使用
fsync系统调用。它会强制将所有待处理的数据从缓存刷新到磁盘,并等待该过程完成。 -
原子性:意味着数据更新要么全部完成,要么完全不进行,不存在中间状态。要实现这一点,一个常见的策略是使用预写日志(Write-Ahead Logging, WAL)。WAL机制会在实际修改数据之前,首先将这些变更记录在一个单独的日志文件中。这样,即便在数据更新过程中发生了崩溃,也可以通过回放日志来恢复到一致的状态。
-
结合使用
fsync和WAL:在执行关键的写操作时,不仅需要调用fsync来确保数据已经物理上写入磁盘,还需要依赖WAL机制来维护数据的原子性。这意味着,在开始任何修改前,先记录变更;然后使用fsync确保这些记录已经被安全地保存;最后才应用这些更改,并再次调用fsync以确保所有更改都已妥善保存。
索引数据结构
通过索引控制延迟和成本
数据库将查询转化为结果,而用户无需了解其内部实现。然而,除了结果本身,延迟和成本(内存、I/O、计算)也是重要的考量因素。这正是分析型(OLAP)和事务型(OLTP)数据库之间的区别所在。
- OLAP:通常涉及大量数据,并执行聚合或连接操作。由于数据量庞大,索引的使用可能有限甚至完全不存在。
- OLTP:处理少量数据时依赖索引来快速访问。目标是低延迟和低成本。
需要注意的是,“事务型”这个词并不是指数据库事务,而只是数据库领域的一个有趣术语。
磁盘数据结构的挑战
-
原地更新问题
在磁盘上更新数据时,如果系统崩溃,可能会导致数据处于损坏状态。磁盘并不是“较慢的RAM”,它的行为与内存完全不同。 -
随机访问 vs. 顺序访问
RAM 中的“R”代表“随机”(Random),这意味着内存支持高效的随机访问。而在磁盘上,即使是固态硬盘(SSD),随机访问也比顺序访问慢得多。因此,像二叉树这样的数据结构在磁盘上并不适用,而 B 树和 LSM 树则更适合。 -
并发访问
数据结构的并发访问也是一个重要话题。多个线程或进程同时访问数据时,需要确保一致性并避免竞争条件。
为什么 B 树和 LSM 树适合磁盘?
B 树
- 特点:B 树是一种平衡树,专为磁盘设计。它的每个节点可以包含多个键值对,从而减少了树的高度,降低了磁盘 I/O 次数。
- 优点:
- 支持高效的范围查询。
- 节点大小通常与磁盘块大小一致,优化了顺序读取性能。
LSM 树(Log-Structured Merge Tree)
- 特点:LSM 树通过将写操作先记录到内存中的缓冲区(MemTable),然后批量写入磁盘的方式来优化写性能。
- 优点:
- 写操作通常是顺序写入,性能较高。
- 适合写密集型工作负载(如日志系统)。
- 缺点:
- 读操作可能需要合并多个文件(SSTables),性能稍差。
OLAP 和 OLTP 的索引策略
-
OLAP:
- 数据量大,查询复杂,索引的作用有限。
- 常用技术包括列式存储和分布式计算框架(如 Apache Spark)。
-
OLTP:
- 数据量小,但要求低延迟。
- 索引是核心,常用结构包括 B 树、哈希索引等。
基于键值对的关联数据库
数据库的两层接口
SQL几乎成为了数据库的代名词,但它实际上只是数据库的一个用户界面,并不是数据库的核心。真正重要的是其底层的功能实现。另一种更为简单的接口是键值(KV)存储。通过KV接口,你可以获取、设置和删除单个键值对,更重要的是,可以以排序顺序列出一系列键。KV比SQL简单,因为它处于更低的一层。关系型数据库就是在类似于KV接口的存储引擎之上构建的。
查询语言:解析器与解释器
尽管代码行数较多,但创建一个查询语言的最后一步其实相对简单——无论是解析器还是解释器,都可以通过递归来实现!这个原则几乎可以应用到任何计算机语言的设计上,或者在创建自己的编程语言或领域特定语言(DSL)时使用。(有关更多挑战,请参考我的书《从源代码到机器码》)
关系型数据库如何建立在键值对之上
-
底层存储:首先,你需要有一个基础的键值存储系统。这个系统允许你执行基本的操作如
GET、SET和DELETE。此外,支持按键排序并列出键范围是非常重要的,这为后续的关系模型提供了必要的功能支持。 -
存储引擎:在KV存储的基础上,构建一个存储引擎。存储引擎负责管理数据的实际存储、索引结构以及事务处理等。对于关系型数据库来说,这意味着需要将表和索引映射到KV存储中的键值对。
-
表与索引的映射:
- 表:每张表可以通过一个唯一的键前缀来标识,表中的每一行则由不同的键表示。例如,键可以设计为
<table_name>:<primary_key>的形式。 - 索引:为了加速查询,可以为常用查询字段建立二级索引。这些索引本身也是KV对,其中键通常是索引字段的值,而值是指向原始记录的引用。
- 表:每张表可以通过一个唯一的键前缀来标识,表中的每一行则由不同的键表示。例如,键可以设计为
-
SQL层:在KV存储和存储引擎之上,添加SQL层。这包括SQL语句的解析器和解释器,它们将SQL查询转换为底层KV操作。例如,一个简单的
SELECT查询可能被转化为一系列的KV查找操作。 -
递归实现解析器和解释器:虽然听起来复杂,但是利用递归技术,可以有效地构建出SQL查询的解析器和解释器。递归使得处理嵌套查询和复杂语法变得更加直观和易于管理。
相关文章:
数据库的基本原则
数据库的核心原则 原子性与持久性:原子性(Atomicity)确保一个事务中的所有操作要么全部完成,要么完全不执行,不会出现部分完成的情况。持久性(Durability)则保证一旦事务提交成功,即…...
Rust 中的Relaxed 内存指令重排演示:X=0 Y=0 是怎么出现的?
🔥 Rust 中的内存重排演示:X0 && Y0 是怎么出现的? 在并发编程中,我们经常会听说“内存重排(Memory Reordering)”这个术语,但它似乎总是只出现在理论或者别人口中的幻觉里。本文将通过…...
C++进程间通信开发实战:高效解决项目中的IPC问题
C进程间通信开发实战:高效解决项目中的IPC问题 在复杂的软件项目中,进程间通信(Inter-Process Communication, IPC)是实现模块化、提高系统性能与可靠性的关键技术之一。C作为一门高性能的编程语言,广泛应用于需要高效…...
FPGA-DDS技术的波形发生器
1.实验目的 1.1掌握直接数字频率合成(DDS)的基本原理及其实现方法。 1.2在DE2-115 FPGA开发板上设计一个可调频率的正弦波和方波发生器,频率范围10Hz~5MHz,最小分辨率小于1kHz。 1.3使用Quartus II进行仿真,并通过S…...
C#实现通过MQTT Broker——EMQX发布订阅消息及其认证、授权的安全配置操作
一、准备内容 MQTT的构成、使用场景、工作原理介绍-CSDN博客文章浏览阅读656次,点赞7次,收藏12次。MQTT(Message Queuing Telemetry Transport)是一种轻量级、基于发布-订阅模式的消息传输协议【适用于资源受限的设备和低带宽、高延迟或不稳定的网络环境】它在物联网应用中…...
考研单词笔记 2025.04.15
addition n添加,增加,加法 additional a附加的,额外的 in addition 另外;除此之外;加之 augment v增加,增强,提高 explode v急剧增长,爆炸,爆发,迸发 gr…...
【双指针】三数之和(medium)
三数之和(medium) 题⽬描述:解法(排序双指针):算法思路:C 算法代码:Java 算法代码:注:数组转列表 题⽬链接:15. 三数之和 题⽬描述: …...
【项目管理】第17章 项目干系人管理-- 知识点整理
项目管理-相关文档,希望互相学习,共同进步 风123456789~-CSDN博客 (一)知识总览 项目管理知识域 知识点: (项目管理概论、立项管理、十大知识域、配置与变更管理、绩效域) 对应:第6章-第19章 第6章 项目管理概论 4分第13章 项目资源管理 3-4分第7章 项目…...
视频融合平台EasyCVR可视化AI+视频管理系统,打造轧钢厂智慧安全管理体系
一、背景分析 在轧钢厂,打包机负责线材打包,操作人员需频繁进入内部添加护垫、整理包装、检修调试等。例如,每班产线超过300件,12小时内人员进出打包机区域超过300次。若员工安全意识薄弱、违规操作,未落实安全措施就…...
无参数RCE
无参数RCE(Remote Code Execution,远程代码执行) 是一种通过利用目标系统中的漏洞,在不直接传递用户可控参数的情况下,实现远程执行任意代码的攻击技术。与传统的RCE攻击不同,无参数RCE不依赖外部输入参数…...
鸿蒙开发中,@Extend、@Styles 和 @Builder 的区别
在鸿蒙(HarmonyOS)开发中,Extend、Styles 和 Builder 是三种常用的装饰器,用于提升代码复用性和可维护性。以下是它们的详细介绍和示例: 1. Extend:扩展组件样式 说明: 功能:用于…...
C++ 智能指针底层逻辑揭秘:优化内存管理的核心技术解读
目录 0.为什么需要智能指针? 1.智能指针的使用及原理 RAII: 智能指针的原理: 2.智能指针有哪些? std::auto_ptr std::unique_ptr std::shared_ptr std::weak_ptr 0.为什么需要智能指针? 想要回答这个问题&…...
Vue接口平台学习七——接口调试页面请求体
一、实现效果图及简单梳理 请求体部分的左边,展示参数,分text和file类型。 右边部分一个el-upload的上传文件按钮,一个table列表展示,一个显示框,用于预览选择的文件,点击可大图展示。 二、页面内容实现 …...
小程序css实现容器内 数据滚动 无缝衔接 点击暂停
<view class"gundongBox"><!-- 滚动展示信息的模块 --><image class"imgWid" :src"imgurlgundong.png" mode"widthFix"></image><view class"gundongView"><view class"container&qu…...
内存条装机,无法启动
1、i5-9600k,主板技嘉z390gamingx: ①、插满4条DDR4-2666,无法启动; ②、两条DDR4-2666,插在2、4或者1、3插槽,可以启动; ③、三条DDR4-2666,一条DDR4-2400,插满4个内存插槽&…...
【力扣】day1
文章目录 27.移除元素26. 删除有序数组的重复项 27.移除元素 26. 删除有序数组的重复项 我们仔细看一下这两道题的最后的返回值,为什么第一题返回slow 而第二题返回slow1 最后的返回值该如何返回绝对不是凭感觉,我们自己分析一下第一个slow,从0位置开始, 遇到val值就开始和fas…...
图像预处理-色彩空间补充,灰度化与二值化
一.图像色彩空间转换 1.1 HSV颜色空间 HSV颜色空间使用色调(Hue)、饱和度(Saturation)和亮度(Value)三个参数来表示颜色 一般对颜色空间的图像进行有效处理都是在HSV空间进行的,然后对于基本…...
linux如何用关键字搜索日志
在 Linux 系统中搜索日志是日常运维的重要工作,以下是几种常用的关键字搜索日志方法: 1. 基础 grep 搜索 bash 复制 # 基本搜索(区分大小写) grep "keyword" /var/log/syslog# 忽略大小写搜索 grep -i "error&…...
Spring Boot项目中结合MyBatis实现MySQL的自动主从切换
原理解析 1. MySQL主从复制(Master-Slave Replication) 工作原理:MySQL主从复制通过二进制日志(binary log)来同步数据。主服务器记录所有更改操作到二进制日志中,从服务器读取这些日志并执行相应的SQL语…...
项目交接时信息遗漏,如何预防
项目交接时,信息遗漏可能导致任务延误、质量下降和团队混乱,因此,建立系统化的交接流程和使用专业的工具是防止信息遗漏的有效策略。交接过程中的信息丢失往往源自沟通不畅、文档不完整或者责任不明确等问题,这不仅影响项目的顺利…...
【AI量化第24篇】KhQuant 策略框架深度解析:让策略开发回归本质——基于miniQMT的量化交易回测系统开发实记
我是Mr.看海,我在尝试用信号处理的知识积累和思考方式做量化交易,应用深度学习和AI实现股票自动交易,目的是实现财务自由~ 目前我正在开发基于miniQMT的量化交易系统——看海量化交易系统。 本篇要讲到量化的核心了——策略。说白了每个投资者…...
向量数据库Qdrant 安装 不使用docker
一、导读 环境:Ubuntu 24.04、Windows 10、WSL 2、Qdrant 1.13.4 背景:换了新工作,使用qdrant作为向量库,需要不使用docker安装 时间:20250415 说明:初入职,不了解,暂且记下 二、…...
微电网与分布式能源:智能配电技术的场景化落地
安科瑞顾强 随着数字化转型与能源革命的加速推进,电力系统正经历从传统模式向智能化、网络化方向的深刻变革。用户侧的智能配电与智能用电技术作为这一变革的核心驱动力,正在重塑电力行业的生态格局。本文将从技术架构、应用场景及未来趋势等维度&#…...
实战指南:封装Whisper为FastAPI接口并实现高并发处理-附整合包
实战指南:封装Whisper为FastAPI接口并实现高并发处理 下面给出一个详细的示例,说明如何使用 FastAPI 封装 OpenAI 的 Whisper 模型,提供一个对外的 REST API 接口,并支持一定的并发请求。 下面是主要步骤和示例代码。 1. 环境准备…...
C#Winform程序将子窗体嵌入容器方法
private void OpenForm(Form childFrom) { //首先判断容器中是否有其他的窗体 foreach (Control item in this.panelRight.Controls) { if (item is Form) { ((Form)item).Close(); } } //嵌入新的窗体 childFrom.TopLevel false;//将子窗体设置成非顶级控件 childFrom.Parent…...
Web三漏洞学习(其一:文件上传漏洞)
靶场:云曦历年考核题 一、文件上传 在此之前先准备一个一句话木马 将其命名为muma.txt 23年秋期末考 来给师兄上个马 打开环境以后直接上传muma.txt,出现js弹窗,说明有前端验证 提示只能上传.png .jpg 和 .gif文件,那就把muma.txt的后缀…...
37-串联所有单词的子串
给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words ["ab","cd","ef"], 那么 "abcdef…...
ShardingSphere复合分片之hash槽算法
前言 上一篇《ShardingSphere复合分片》中有详细介绍多key多value的复合分片算法应该如何设计,在大部分情况下该算法是没有问题的,但是一旦涉及到数据迁移时,该算法的缺点就暴露无疑了。 为满足日益增长的用户或者订单的需求,在分…...
Web三漏洞学习(其二:sql注入)
靶场:NSSCTF 、云曦历年考核题 二、sql注入 NSSCTF 【SWPUCTF 2021 新生赛】easy_sql 这题虽然之前做过,但为了学习sql,整理一下就再写一次 打开以后是杰哥的界面 注意到html网页标题的名称是 “参数是wllm” 那就传参数值试一试 首先判…...
KrillinAI:视频跨语言传播的一站式AI解决方案
引言 在全球内容创作领域,跨语言传播一直是内容创作者面临的巨大挑战。传统的视频本地化流程繁琐,涉及多个环节和工具,不仅耗时耗力,还常常面临质量不稳定的问题。随着大语言模型(LLM)技术的迅猛发展,一款名为Krillin…...
