badgerdb里面的事务

事务的ACID

  • A 原子性(Atomicity)
    多步骤操作,只能是两种状态,要么所有的步骤都成功执行,要么所有的步骤都不执行,举例说明就是小明向小红转账30元的场景,拆分成两个步骤,步骤1:小明减30元。步骤2:小红加30元。步骤1和2必须同时执行成功或失败,不能只执行其中的一个步骤。

  • C 一致性(Consistency)
    其实和原子性一样

  • I 隔离性(Isolation)
    多个事务执行时,不能受并发的事务的影响,后面会详细的说隔离级别

  • D 持久性(Durability)
    事务一旦提交落盘后,数据不会因为程序异常或断电丢失数据

隔离性

  1. 读未提交(Read uncommitted)
  2. 读已提交(Read committed)
  3. 可重复读(Repeatable read)
  4. 序列化(Serializable )
    从上到下,四个级别的隔离性依次变强,性能依次变差

在这里插入图片描述
读未提交 :对应脏读,在本事务的线段内,会读到其他线段的中间状态。
读已提交:对应不可重复读,比上个好一些。该级别下不能读到其他事务的未提交状态。但如上图,如果事务 t2 在执行时,多次读某个记录 x 的状态,在事务 t1 未启动前,发现 x = 2,在事务 t1 提交后,发现 x = 3,这便出现了不一致。
可重复读:如上图,事务 t2 在整个执行期间,多次读取数据库 x 的状态,无论他事务(如 t1)是否改变 x 状态并提交,事务 t2 都不会感觉到。但是会存在幻读的风险。怎么理解呢?最关键的原因在于写并发。因为读不到,不代表其他事务的影响不存在。比如事务 t2 开始时,通过查询发现 id = “qtmuniao” 的记录为空,于是创建了 id=“qtmuniao” 的记录,然而在提交时,发现报错说该 id 已经存在。这可能是因为有一个开始的比较晚的事务 t2,也创建了一个 id=“qtmuniao” 的记录,但是先提交了。于是用户就郁闷了,明明你说没有,但我写又报错,难道我出现幻觉了?这就太扯淡了,但是此级别就只能做到这样了。反而,因为兼顾了性能和隔离性,他是大多数据库的默认级别。
序列化:最简单的实现办法就是一把锁来串行化所有的事务boltdb就是这么做的。badgerdb在此基础上如果能提高并发,做很多优化。

badger 的序列化SSI

badgerdb 的事务主要依靠多个tnx结构体和全局的一个oracle结构体来维护

type Txn struct {
	readTs   uint64
	commitTs uint64
}

type oracle struct {
	nextTxnTs   uint64
}

每一个txn都有readTs和commitTs ,其中全局的o.nextTxnTs只有获得提交时间戳的时候才加1,如果多个事务并发,任何一个事务都还没有提交的时候,这些事务获得的readTs 是一样的

	var readTs uint64
	o.Lock()
	readTs = o.nextTxnTs - 1//txn 的readTs
	o.readMark.Begin(readTs)
	o.Unlock()


	ts = o.nextTxnTs
	o.nextTxnTs++//事务获得了提交时间后,再把nextTxnTs+1
	o.txnMark.Begin(ts)

创建一个事务的时候,要进行授时txn.readTs = db.orc.readTs(),这个时间是一个递增的序列,接下来主要来分析一下db.orc.readTs()这个函数,获得readTs后会等待readTs这个时间戳提交的事务彻底写入LSM tree后才返回,保证了不会脏读,不会读到其他未提交的事务,和不可重复读

func (o *oracle) readTs() uint64 {
	if o.isManaged {
		panic("ReadTs should not be retrieved for managed DB")
	}

	var readTs uint64
	o.Lock()
	readTs = o.nextTxnTs - 1
	o.readMark.Begin(readTs)
	o.Unlock()

	// Wait for all txns which have no conflicts, have been assigned a commit
	// timestamp and are going through the write to value log and LSM tree
	// process. Not waiting here could mean that some txns which have been
	// committed would not be read.
	y.Check(o.txnMark.WaitForMark(context.Background(), readTs))
	return readTs
}


badgerdb 解决幻读

在上文描述的可重复读,出现的幻读,badgerdb解决幻读和不可重复读的方法就是事务t2放弃提交,给用户层返回ErrConflict错误,让用户层稍后再试。

先找到代码中报ErrConflict的地方,是获取CommitTs的时候报的错误

func (txn *Txn) commitAndSend() (func() error, error) {
	orc := txn.db.orc
	// Ensure that the order in which we get the commit timestamp is the same as
	// the order in which we push these updates to the write channel. So, we
	// acquire a writeChLock before getting a commit timestamp, and only release
	// it after pushing the entries to it.
	orc.writeChLock.Lock()
	defer orc.writeChLock.Unlock()

	commitTs, conflict := orc.newCommitTs(txn)
	if conflict {
		return nil, ErrConflict
	}
}

进去看orc.newCommitTs(txn)

func (o *oracle) newCommitTs(txn *Txn) (uint64, bool) {
	o.Lock()
	defer o.Unlock()

	if o.hasConflict(txn) {
		return 0, true
	}
}

再看o.hasConflict(txn);
txn.reads 是被txn.addReadKey进行修改的;
committedTxn.conflictKeys 是txn.modify() 修改的,txn.modify()是txn.Set或txn.Detele调用的;
总结下来就是:当前事务如果读过的key,在当前事务的readTs后有在其他的事务对这些读到过的key做过修改,那么本次事务就是有冲突的

// hasConflict must be called while having a lock.
func (o *oracle) hasConflict(txn *Txn) bool {
	if len(txn.reads) == 0 {
		return false
	}
	for _, committedTxn := range o.committedTxns {
		// If the committedTxn.ts is less than txn.readTs that implies that the
		// committedTxn finished before the current transaction started.
		// We don't need to check for conflict in that case.
		// This change assumes linearizability. Lack of linearizability could
		// cause the read ts of a new txn to be lower than the commit ts of
		// a txn before it (@mrjn).
		if committedTxn.ts <= txn.readTs {
			continue
		}

		for _, ro := range txn.reads {
			if _, has := committedTxn.conflictKeys[ro]; has {
				return true
			}
		}
	}

	return false
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/78149.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

华为将收取蜂窝物联网专利费,或将影响LPWAN市场发展

近日&#xff0c;华为正式公布了其4G和5G手机、Wi-Fi6设备和物联网产品的专利许可费率&#xff0c;其中包含了长距离通信技术蜂窝物联网。作为蜂窝物联网技术的先驱&#xff0c;华为是LTE Category NB (NB-IoT)、LTE Category M和其他4G物联网标准的主要贡献者。 在NB-IoT领域…

ArcGIS Pro如何制作不规则形状图例

在默认的情况下&#xff0c;ArcGIS Pro生成的图例是标准的点、直线和矩形的&#xff0c;对于湖泊等要素而言&#xff0c;这样的表示方式不够直观&#xff0c;我们可以将其优化一下&#xff0c;制作不规则的线和面来代替原有图例&#xff0c;这里为大家介绍一下制作方法&#xf…

用二进制来输出一个数

用二进制来输出一个数 1&#xff0c;一个数 #include <stdio.h> #include <stdlib.h> #include <stdint.h>int main() {uint32_t m 0x00C00000;printf("m%o,m%d,m0x%x\n",m,m,m);binary(m);return 0; }2&#xff0c;方法 void binary(uint32_t…

rabbitmq的死信队列

目录 成为死信的条件 消息TTL过期 队列达到最大长度 消息被拒 延迟队列 延迟队列使用场景 消息设置 TTL 队列设置 TTL 两者区别 producer 将消息投递到 broker 或者直接到 queue 里了&#xff0c; consumer 从 queue 取出消息 进行消费&#xff0c;但某些时候由…

煤矿调度IP语音对讲广播模块一键求助对讲矿用调度通信系统SIP语音对讲求助终端

硬件接口描述 SV-2101VP/ SV-2103VP系列网络音频模块&#xff0c;所有外部连接采用端子&#xff0c;电源采用2.0mm的端子&#xff0c;网络采用标准RJ45连接器&#xff0c;其他都是1.25mm的连接器。 端口类型定义 P ———— 电源 AI ———— 模拟输入&#xff08;在这里是音…

ArcGIS Pro基础入门、制图、空间分析、影像分析、三维建模、空间统计分析与建模、python融合、案例全流程科研能力提升

目录 第一章 入门篇 GIS理论及ArcGIS Pro基础 第二章 基础篇 ArcGIS数据管理与转换 第三章 数据编辑与查询、拓扑检查 第四章 制图篇 地图符号与版面设计 第五章 空间分析篇 ArcGIS矢量空间分析及应用 第六章 ArcGIS栅格空间分析及应用 第七章 影像篇 遥感影像处理 第八…

java 工程管理系统源码+项目说明+功能描述+前后端分离 + 二次开发 em

Java版工程项目管理系统 Spring CloudSpring BootMybatisVueElementUI前后端分离 功能清单如下&#xff1a; 首页 工作台&#xff1a;待办工作、消息通知、预警信息&#xff0c;点击可进入相应的列表 项目进度图表&#xff1a;选择&#xff08;总体或单个&#xff09;项目显…

软件测试项目实战,电商业务功能测试点汇总(全覆盖)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 支付功能怎么测试…

银河麒麟服务器v10 sp1 .Net6.0 Serilog 运行时不创建日志文件

上一篇&#xff1a;银河麒麟服务器v10 sp1 .Net Core 上传文件错误_csdn_aspnet的博客-CSDN博客 在代码中常用的日志记录相关重要或错误日志等&#xff0c;如Serilog、Log4net等&#xff0c;本文使用Serilog&#xff0c;在Program.cs的main方法中&#xff0c;代码如下图&#…

RabbitMq-3入门案例

rabbitmq入门 1.生产者&#xff08;服务提供方&#xff09; //依赖<dependencies> <!-- rabbitmq客户端依赖--><dependency><groupId>com.rabbitmq</groupId><artifactId>amqp-client</artifactId><version>5.8.0<…

半导体退火那些事(3)

4.半导体退火设备 双腔全自动兼容6-8寸快速退火炉RTP 产地:中国 型号: S803 特点: 室温到1250C&#xff0c;应用于SiC&#xff0c;GaN等第三代半导体领域 简介 (Description) S803系列自动快速退火炉&#xff0c;内置Robot可以自动取放片&#xff0c;适用于最大8英寸 (单片200m…

css内容达到最底部但滚动条没有滚动到底部

也是犯了一个傻狗一样的错误 &#xff0c;滚动条样式是直接复制的蓝湖的代码&#xff0c;有个高度&#xff0c;然后就出现了这样的bug 看了好久一直以为是布局或者overflow的问题&#xff0c;最后发现是因为我给这个滚动条加了个高度&#xff0c;我也是傻狗一样的&#xff0c;…

494. 目标和

494. 目标和 原题链接&#xff1a;完成情况&#xff1a;解题思路&#xff1a;数组回溯法动态规划 参考代码&#xff1a;数组回溯法__494目标和__动态规划 经验吸取 原题链接&#xff1a; 494. 目标和 https://leetcode.cn/problems/target-sum/description/ 完成情况&#…

openCV使用c#操作摄像头

效果如下&#xff1a; 1.创建一个winform的窗体项目&#xff08;框架.NET Framework 4.7.2&#xff09; 2.Nuget引入opencv的c#程序包&#xff08;版本最好和我一致&#xff09; 3.后台代码 using System; using System.Collections.Generic; using System.ComponentModel;…

Redis系列(三):深入解读Redis主从同步机制

首发博客地址 https://blog.zysicyj.top/ Redis高可靠靠什么保证&#xff1f; 为什么要提这个呢&#xff0c;因为Redis主从库目的呢其实就是为了实现高可靠。上篇文章中我们说过Redis的AOF、RDB日志其实就是为了减少数据丢失&#xff0c;这是高可靠的一部分。 这篇文章呢&#…

爬虫逆向实战(六)--猿人学第四题

一、数据接口分析 主页地址&#xff1a;猿人学第四题 1、抓包 通过抓包可以发现数据接口是api/match/4 2、判断是否有加密参数 请求参数是否加密&#xff1f; 无请求头是否加密&#xff1f; 无响应是否加密&#xff1f; 响应数据无加密&#xff0c;但是返回的却是html代码…

展会邀请 | 虹科诚邀您参加8月16日深圳视觉系统设计技术会议

VisionCon视觉系统设计技术会议 将于8月16日在深圳深铁皇冠假日酒店隆重举行&#xff01; 人力成本的提高、国际关系的不确定性等众多因素&#xff0c;都在促使中国制造业采用更先进的自动化及智能化技术&#xff0c;同时也在加速核心技术的国产化。作为智能制造不可或缺的关…

Ubuntu中安装OpenSSL

文章目录 一、前期准备1.1 压缩包下载1.2 gcc, make等的安装二、安装配置 一、前期准备 1.1 压缩包下载 在安装openssl之前&#xff0c;我们需要下载对应的压缩包 https://www.openssl.org/source/openssl-3.0.1.tar.gz 此压缩包可以选择win上下载后解压再复制到本地虚拟机中…

Linux 基础命令

文件系统 Linux文件系统结构与Windows有些不同。Linux在文件系统的基础上没有物理驱动器&#xff08;例如C&#xff1a;驱动器&#xff09;&#xff0c; 而是使用逻辑文件系统。在文件系统结构的最顶层是/&#xff0c;它通常被称为文件系统的根&#xff0c;就好像它是一个倒置 …

从零开始打造家装预约咨询小程序

在如今互联网高度发达的时代&#xff0c;家装行业也逐渐意识到了线上渠道的重要性。为了更好地服务客户&#xff0c;提高用户体验&#xff0c;越来越多的家装公司开始寻找合适的小程序制作平台。本文将向大家介绍如何使用第三方制作平台&#xff0c;如乔拓云网&#xff0c;打造…