高效DEBUG事务正确性BUG

作者:张旭 MO研发工程师

目录

Part 1. 事务回顾

Part 2. 事务的正确性问题

Part 3. 如何高效 DEBUG

熟悉数据库分布式事务的读者,应该能够理解DEBUG分布式事务正确性问题的BUG是一件非常有挑战的事情。本文主要是给大家介绍一下,MatrixOne在研发过程中,是如何DEBUG事务正确性问题的。

1. 事务回顾

我们首先来回顾一下,在 MatrixOne 中,事务是如何实现的。

1.1 数据存在哪儿

MatrixOne 是一个云原生的数据库,数据库中大部分的数据都存储在对象存储(可以是任何S3兼容的对象存储)中,这部分数据是不变的。数据不可变带来了非常多的好处,比如不需要考虑这些数据的一致性问题。

除了存储在对象存储中的数据外,还有非常少的数据存储在LogService中,LogService是一个使用 Raft 实现的高性能的 WAL 服务。这部分数据在 MatrixOne 中被称为 LogTail。这部分数据是变化的,可以认为是 MatrixOne 集群最新的 Commit 数据。

对象存储 + LogTail组成了 MatrixOne 的全量数据。

1.2 事务隔离级别

MatrixOne 的事务支持RCSI的隔离级别,默认是RC

1.3 事务模式

MatrixOne 的事务支持悲观乐观的模式,默认是悲观

1.4 事务并发控制

MatrixOne 使用 MVCC 来实现事务并发控制。并且使用 HLC 来实现事务时钟。

1.5 事务读操作

对于事务的读操作而言,首先需要确定的就是哪些数据对于事务是可见的。在任何一个时刻,对于事务可见的数据包括:

  1. 对象存储中所有CommitTimestamp < txn.SnapshotTimestamp的数据
  2. LogTail中所有CommitTimestamp < txn.SnapshotTimestamp的数据
  3. 事务的Workspace中所有的Uncommitted的数据

在我们明确哪些数据对于事务是可见的时候,就需要确定满足条件的数据在读发生的时候,是否完整。

Workspace中的数据,任何时刻对于事务都是完整的。需要保证的就是对象存储LogTail的数据了。由于LogTail是整个 MatrixOne 集群最新的数据写入,所以只要保证LogTail的数据完整了,那么对象存储对应的数据对于事务也就完整了。

现在的问题就是如何保证LogTail的数据对于事务是完整的。

MatrixOne 的事务在CN节点创建,事务创建后,就会明确一个事务的SnapshotTimestamp(这个时间戳对于SI是整个事务生命周期不变的,对于RC是每个Statement的生命周期内是不变的)。

LogTail的数据在TN节点产生,并且写入LogService。CN使用订阅的方式来获得最新的LogTail数据,并且把这些LogTail中的数据Apply到CN的内存中。

CN在内存中维护了一个最大的ApplyCommitTimestamp,可以根据这个时间戳的水位和事务的SnapshotTimestamp来确保,LogTail的数据对于事务是完整的。

1.6 事务的写操作

MatrixOne 事务的 Uncommitted 的数据,都是写入 Workspace,这个 Workspace 在CN的内存中。

一个事务写入的数据越多,这个Workspace占用的内存越大,知道OOM发生。MatrixOne 为了解决这个问题,对于Workspace的内存大小有一个阈值(默认是1MB),当发现Workspace的内存超过这个阈值,就会把Workspace中的数据写入到对象存储,在Workspace的数据会被替换成对象存储上临时文件名

事务在没有Commit之前,不会和TN交互,在Commit的时候,会把Workspace的数据发送给TN节点做Commit处理。

2. 事务的正确性问题

2.1 什么是正确性问题

上面的章节我们回顾了事务,现在需要说明一下,什么事事务正确性的问题。在 MatrixOne 的研发过程中遇到事务正确性的BUG主要有以下几种:

  • RC模式下的Lost Update
  • 悲观事务锁服务失效
  • Workspace数据问题

这几个问题都会产生事务正确性问题。这些问题,都会产生事务读了错误的数据,或者提交了错误的数据。

2.2 如何测试

MatrixOne 很多的测试,来帮助我们发现这些事务正确问题,这些测试包括:

  • 单元测试
  • 集成测试
  • PR Merge之前的CI测试
  • PR Merge之后的性能基准测试
  • 7*24小时执行的稳定性测试
  • daily的各种测试
  • chaos 测试

这些测试都会帮助我们发现事务正确性问题。

2.3 常规分析问题的手段

对于研发来说,我们常规的分析问题的手段一半是这几种:

  • 断点Debug
  • 分析日志
  • Metrics
  • Tracing

对于分析分布式集群的事务问题,其中最有用的就是日志,其余手段几乎没有用。断点DEBUG只能分析必现的问题,Metrics只能观测到系统的一个大概情况,不能定位数据问题。Tracing一般是指调用链监控,可以用来分析性能问题,但是对于数据错误的问题,无法提供帮助。

总结来看,分析正确性问题几乎只有日志可用。

2.3.1 需要哪些日志

事务正确性问题,归根结底是对于一行记录,读到了错误的数据或者写入错误的数据。这个问题的本身,是数据的内容错了。数据的内容错了,问题可能出现在这行数据所有发生读写的地方。

如果我们需要分析事务正确性问题,那么就需要分析问题出在哪一个事务发生读写的地方。并且还有一个条件,就是能够根据出问题的事务,出问题的行,把这些地方的日志信息全部串联起来,就可以找到问题所在。

但是问题是复杂的,由于悲观事务的模式,多个并发事务会相互影响,所以还需要串联起来有冲突的事务的所有相关信息一起分析。

2.3.2 日志的问题

我们分析问题需要那些信息,上文我们分析了,这些信息需要都记录到日志中。这些日志不可能运行在Info的日志级别,只能在DEBUG级别。这样就带来了一些问题:

  • 在一些测试中无法打开DEBUG级别的日志

    在性能测试中,是无法打开DEBUG日志的。如果错误出现在性能测试中出现,几乎无法分析。

  • DEBUG日志难以重现问题

    事务正确性问题,有时候非常难以重现,可能需要满足特定的并发时序。如果是在不能打开DEBUG的测试中出现,需要打开DEBUG日志级别,跑一样的负载,DEBUG日志过多,改变了系统运行的时序,问题会更加难以复现。

  • 日志难以分析

    当具备完备的DEBUG的日志的时候,这个日志的规模可能非常非常大,并且是一个在分布式环境中,产生的各自节点和进程的日志,分析的难度也是异常艰难的。

3. 如何高效DEBUG

在 MatrixOne 的研发过程中,Fix 事务正确性的BUG,一直是痛苦的经历。MatrixOne 还处于快速发展阶段,系统中有非常多的优化还没有去处理,这些修改,都有可能带来新的事务正确性的BUG。所以我们需要一个高效DEBUG事务正确性BUG的工具和方法。

3.1 设计目标

使用日志去分析的问题弊端,我们已经有扩深刻的经历。现在需要达成的设计目标有3点:

  • 在任何测试场景中,只要出现BUG,不需要重新复现,就有足够的信息分析问题
  • 不能对于性能测试有太大的影响,10%以内的性能影响是可以接受的
  • 要提供非常丰富的分析信息的方式和手段

3.2 设计挑战

在测试中会产生非常巨大的需要分析的数据。这些数据如何存储,如何提供丰富的分析查询能力。因为分析问题的时候,需要根据各种各样的条件去分析查询信息。

3.2.1 如何提供分析查询能力

首先我们不考虑数据如何存储,先来看如何提供数据查询分析能力,解决了这个问题,可能数据如何存储的问题就解决了。

目前为止,没有比以SQL的方式来提供这些数据的查询更方便的,语意更丰富能力的分析查询方式了。如果我们可以提供一SQL的方式来提供DEBUG数据的分析查询能力,这个好处是显而易见的,并且DEBUG的效率也是提升巨大的。

所以我们决定以SQL的方式提供DEBUG数据的查询分析。

3.2.2 数据如何存储

存储方式就显而易见了,因为提供SQL的方式来提供查询能力,那么数据就需要存储的数据库中。所以我们需要一个能够提供强大AP能力的数据库来存储这些DEBUG数据。

结论显而易见了,MatrixOne 自己就是一个支持高性能AP查询的数据库。

3.2.3 数据如何写入

我们有一个设计目标是,开启收集DEBUG信息的时候,对于性能不能有超过10%的性能影响。我们需要对数据写入到数据库有一些特殊的设计:

  • 异步以Load的方式写入数据到数据库
  • DEBUG数据的写入可以skip掉事务中一些耗时的操作(去重,冲突检测)
  • 尽可能的减少不必要的信息

3.3 Trace框架设计

从 MatrixOne 1.2版本开始,MatrixOne 提供一个mo_debug的内置数据库,并且根据之前分析日志的经验,对分析事务问题需要的数据进行了抽象,提供了一些表来存储数据。

并且提供了一些专门的语句来动态的打开和关闭Trace的功能。

由于篇幅问题,本文不会描述这些表的具体设计含义,只会简单介绍一下,主要目的还是给分享一下思路。

3.3.1 数据表
create table trace_event_txn (ts 			      bigint       not null,txn_id            varchar(50)  not null,cn                varchar(100) not null,event_type        varchar(50)  not null,txn_status	      varchar(10),snapshot_ts       varchar(50),commit_ts         varchar(50),info              varchar(1000)
)create table trace_event_data (ts 			      bigint          not null,cn                varchar(100)    not null,event_type        varchar(50)     not null,entry_type		  varchar(50)     not null,table_id 	      bigint UNSIGNED not null,txn_id            varchar(50),row_data          varchar(500)    not null, committed_ts      varchar(50),snapshot_ts       varchar(50)
)create table trace_event_txn_action (ts 			      bigint          not null,txn_id            varchar(50)     not null,cn                varchar(50)     not null,table_id          bigint UNSIGNED,action            varchar(100)    not null,action_sequence   bigint UNSIGNED not null,value             bigint,unit              varchar(10),err               varchar(100) 
)create table trace_event_error (ts 			      bigint          not null,txn_id            varchar(50)     not null,error_info        varchar(1000)   not null
)create table trace_statement (ts 		   bigint          not null,txn_id     varchar(50)     not null,sql        varchar(1000)   not null,cost_us    bigint          not null 
)

这些数据表主要记录了,在执行过程中所有数据发生的写入,读取,以及事务的元数据变更,执行的SQL,并发冲突等等关键信息。

3.3.2 Filter表
create table trace_table_filters (id              bigint UNSIGNED primary key auto_increment,table_id	    bigint UNSIGNED not null,table_name      varchar(50)     not null,columns         varchar(200)
);create table trace_txn_filters (id             bigint UNSIGNED primary key auto_increment,method         varchar(50)     not null,value          varchar(500)    not null
);create table trace_statement_filters (id             bigint UNSIGNED primary key auto_increment,method         varchar(50)     not null,value          varchar(500)    not null
);

这些Filter表,用来做过滤,尽可能的减少需要记录的数据量。

3.4 效果

打开Trace后,对于性能的影响在5%左右。依靠 MatrixOne 提供能的高性能的AP查询服务能力,研发人员可以根据SQL来查询DEBUG问题,查询执行期间所有需要的数据变更,事务元数据变更等等所有的对于DEBUG问题有帮助的信息。

这样极大的提高了效率,提升了 FIX 事务正确性的BUG的速度。

About MatrixOne

MatrixOne 是一款基于云原生技术,可同时在公有云和私有云部署的多模数据库。该产品使用存算分离、读写分离、冷热分离的原创技术架构,能够在一套存储和计算系统下同时支持事务、分析、流、时序和向量等多种负载,并能够实时、按需的隔离或共享存储和计算资源。 云原生数据库MatrixOne能够帮助用户大幅简化日益复杂的IT架构,提供极简、极灵活、高性价比和高性能的数据服务。

MatrixOne企业版和MatrixOne云服务自发布以来,已经在互联网、金融、能源、制造、教育、医疗等多个行业得到应用。得益于其独特的架构设计,用户可以降低多达70%的硬件和运维成本,增加3-5倍的开发效率,同时更加灵活的响应市场需求变化和更加高效的抓住创新机会。在相同硬件投入时,MatrixOne可获得数倍以上的性能提升。

关键词:超融合数据库、多模数据库、云原生数据库、国产数据库。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

选哪个短剧系统源码好:全面评估与决策指南

在短剧内容创作和分享日益流行的今天&#xff0c;选择合适的短剧系统源码对于构建一个成功的短剧平台至关重要。短剧系统源码不仅关系到平台的稳定性和用户体验&#xff0c;还直接影响到内容创作者和观众的互动质量。本文将提供一份全面的评估指南&#xff0c;帮助您在众多短剧…

七一建党节|热烈庆祝中国共产党成立103周年!

时光荏苒&#xff0c;岁月如梭。 在这热情似火的夏日&#xff0c; 我们迎来了中国共产党成立103周年的重要时刻。 这是一个值得全体中华儿女共同铭记和庆祝的日子&#xff0c; 也是激励我们不断前进的重要时刻。 103年&#xff0c; 风雨兼程&#xff0c;砥砺前行。 从嘉兴…

拓扑排序[讲课留档]

拓扑排序 拓扑排序要解决的问题是给一个有向无环图的所有节点排序。 即在 A O E AOE AOE网中找关键路径。 前置芝士&#xff01; 有向图&#xff1a;有向图中的每一个边都是有向边&#xff0c;即其中的每一个元素都是有序二元组。在一条有向边 ( u , v ) (u,v) (u,v)中&…

解析QAnything启动命令过程

一.启动命令过程日志 启动命令bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat。输入日志如下所示&#xff1a; rootMM-202203161213:/mnt/l/20230918_RAG方向/QAnything# bash ./run.sh -c local -i 0 -b hf -m Qwen-1_8B-Chat -t qwen-7b-chat From …

快钱支付股东全部股权已被质押!

根据近期工商信息&#xff0c;第三方支付机构快钱支付清算信息有限公司&#xff08;简称“快钱支付”&#xff09;实际控股方快钱金融服务&#xff08;上海&#xff09;有限公司&#xff08;简称“快钱金融”&#xff09;&#xff0c;作为出质股权标的企业&#xff0c;被出质给…

Python容器 之 列表--定义

1.什么是列表呢&#xff1f; 列表(list)是 Python 中使用最频繁的数据类型, 在其他语言中通常叫做数组, 专门用来存储一组数据 列表,list, 使用 [ ] 列表可以存放任意多个数据 列表中可以存放任意类型的数据 列表中数据之间 使用 逗号隔开 2.列表如何定义&#xff1f; &#…

面向阿克曼移动机器人(自行车模型)的LQR(最优二次型调节器)路径跟踪方法

线性二次调节器&#xff08;Linear Quadratic Regulator&#xff0c;LQR&#xff09;是针对线性系统的最优控制方法。LQR 方法标准的求解体系是在考虑到损耗尽可能小的情况下, 以尽量小的代价平衡其他状态分量。一般情况下&#xff0c;线性系统在LQR 控制方法中用状态空间方程描…

Redis慢查询

Redis慢查询 目录 Redis慢查询慢查询配置慢日志操作返回参数介绍 Redis的慢查询就是当命令执行时间超过预定的阈值后将这条命令记录下来&#xff0c;与MySQL的功能类似 慢查询配置 默认阈值是10毫秒&#xff0c;即10000微秒 临时修改阈值为20毫秒 127.0.0.1:6379> confi…

docker配置redis主从复制

下载redis,复制redis.conf 主节点(6379) 修改redis.conf # bind 127.0.0.1 # 注释掉这里 protected-mode no # 改为no port 6379从节点(6380) 修改redis.conf bind 127.0.0.1 protected-mode no # 改为no port 6380 replicaof 172.17.0.2 6379 # 这里的ip为主节点容器的i…

Zuul介绍

Zuul 是 Netflix 开源的一个云平台网络层代理&#xff0c;它主要用于路由、负载均衡、中间件通信和动态路由。Zuul 本质上是一个基于 JVM 的网关&#xff0c;它提供了以下功能&#xff1a; 1.路由&#xff1a;Zuul 允许客户端和服务器之间的所有入站和出站请求通过一个中心化的…

深度挖掘数据资产,洞察业务先机:利用先进的数据分析技术,精准把握市场趋势,洞悉客户需求,为业务决策提供有力支持,实现持续增长与创新

在当今日益激烈的商业竞争环境中&#xff0c;企业想要实现持续增长与创新&#xff0c;必须深入挖掘和有效运用自身的数据资产。数据不仅是企业运营过程中的副产品&#xff0c;更是洞察市场趋势、理解客户需求、优化业务决策的重要资源。本文将探讨如何通过利用先进的数据分析技…

Python容器 之 字符串--下标和切片

1.下标&#xff08;索引&#xff09; 一次获取容器中的一个数据 1, 下标(索引), 是数据在容器(字符串, 列表, 元组)中的位置, 编号 2, 一般来说,使用的是正数下标, 从 0 开始 3, 作用: 可以通过下标来获取具体位置的数据. 4, 语法&#xff1a; 容器[下标] 5, Python 中是支持…

进程,线程,虚拟内存,交换技术

参考资料&#xff1a; 参考视频1https://www.bilibili.com/video/BV1Hs421M78w/?spm_id_from333.999.0.0&vd_source97411b9a8288d7869f5363f72b0d7613 参考视频2https://www.bilibili.com/video/BV1jE411W7e8/?spm_id_from333.337.search-card.all.click&vd_source…

独家首发 | Matlab实现SVM-Transformer多变量回归预测

独家首发 | Matlab实现SVM-Transformer多变量回归预测 目录 独家首发 | Matlab实现SVM-Transformer多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现SVM-Transformer多变量回归预测&#xff0c;SVM递归特征消除Transformer多输入单输出回归预测…

从项目中学习Bus-Off的快慢恢复

0 前言 说到Bus-Off&#xff0c;大家应该都不陌生&#xff0c;使用VH6501干扰仪进行测试的文章在网上数不胜数&#xff0c;但是一般大家都是教怎么去干扰&#xff0c;但是说如何去看快慢恢复以及对快慢恢复做出解释比较少&#xff0c;因此本文以实践的视角来讲解Bus-Off的快慢恢…

STM32人体心电采集系统

资料下载地址&#xff1a;STM32人体心电采集系统 1、项目功能介绍 此项目主要实现了以STM32为核心的人体心电采集系统软硬件的设计。软件设计过程是在STM32上移植的uCGUI做图形界面&#xff0c;并如实显示采集到的心电波形信号&#xff0c;有SD卡存储和USB数据传输功能。 2、实…

反激开关电源反馈电路相关参数选型

Vb的电压正常变化范围是&#xff1a;0-1V&#xff08;最低0V&#xff0c;由于有稳压管&#xff0c;最高不会超过1V&#xff09; Vb的电压越高&#xff0c;则输出占空比越大&#xff0c;Vb电压越低&#xff0c;则输出占空比越小 那么Va的正常变化范围应该是&#xff1a;1.4-4.…

阅读这篇文章,彻底了解响应式网页设计

随着移动设备的普及&#xff0c;访问网站的方式发生了翻天覆地的变化。人们不再仅仅依靠桌面机来获取信息和享受在线服务。这给网页设计带来了巨大的挑战。如何构建一个能够在各种设备上流畅运行并提供一致用户体验的网站&#xff0c;已经成为每个网页设计师关心的问题。此时&a…

超详细之IDEA上传项目到Gitee完整步骤

1. 注册gitee 账号密码&#xff0c;gitee官网地址&#xff1a;Gitee官网&#xff0c;注册完成后&#xff0c;登录。 2. 创建仓库&#xff0c;在主页左下角有新建按钮&#xff0c;点击新建后会进入到此页面填写仓库信息。 3. 创建完成后复制仓库地址 4. 打开IntelliJ IDEA新建或…

java基于ssm+jsp 房屋租赁系统

1 管理员登录 管理员输入个人的用户名、密码登录系统&#xff0c;这时候系统的数据库就会在进行查找相关的信息&#xff0c;如果我们输入的用户名、密码不正确&#xff0c;数据库就会提示出错误的信息提示&#xff0c;同时会提示管理员重新输入自己的用户名、密码&#xff0c;…