Java开发 - 数据库中的基本数据结构(三)

简介: Java开发 - 数据库中的基本数据结构

隐藏字段作用


下面,我们通过下面的表来表示三个隐藏字段工作的原理:


用户表user,事务A执行插入张三数据之后:

id name age db_trx_id db_roll_ptr
1 张三 20 1 null(刚插入,无回滚地址)

用户表user,事务B执行修改张三年龄数据之后:

id name age db_trx_id db_roll_ptr
1 张三 30 2 0x10010001(假设这是张三之前的地址)

undolog:

事务A执行之后undolog内产生一条新纪录

id name age db_trx_id db_roll_ptr
1 张三 20 1 null

事务B执行之后undolog内产生一条新纪录

id name age db_trx_id db_roll_ptr
1 张三 30 2 0x10010001

如果还有其他的事务操作这条数据,以此类推即可。


ReadView


在事务执行的时候,就会生成当前事务的ReadView,用于保存当前事务之前活跃的所有事务id,之前活跃的事务的最小id,当前事务结束后即将分配的下一个id,创建ReadView的当前事务id,名字分别如下:


m_ids: 截止到当前事务id之前,所有的活跃事务id

min_trx_id: 记录以上活跃事务id中的最小id值

max_trx_id: 保存当前事务结束后应分配的下一个id值

creator_trx_id: 保存创建ReadView的当前事务的id

我们用几张表来表示下三者结合的工作过程:


给出一个事务操作后形成的用户表:


事务1插入张三


事务2插入李四

id name age db_trx_id db_roll_ptr
1 张三 20 1 null
2 李四 25 2 null

模拟并发事务的工作过程:

时刻 事务A   id:8 事务B   id:9
t1 begin
t2 beigin
t3 查询张三的年龄为20
t4 修改张三的年龄为30

t5

commit
t6

再次查询张三的age,MVCC下应为20

t7 commit

事务AB工作时会分别生成自己的ReadView:

  事务A的ReadView:

m_ids

min_trx_id max_trx_id creator_trx_id
假设为3,4,5,6 3 9(下一个应分配事务id) 8(当前事务id)

所有的select不加锁,所以都是执行的快照读,所以后面的事务可以从undolog中读取到之前的事务执行的状态,所以在做查询时必须参考之前的快照。


现在开始分析事务8和9每个时刻的操作。


在t3时刻,查询张三的年龄时:


先去看这条数据是否在m_ids中,若果在,则处于活跃状态,说明这条数据还没提交,则不能访问,若不在,说明在当前事务之前已经提交,则可以访问,接着去查找创建这条数据的事务id是否小于当前事务id,如果小于,那一定是在当前事务之前已经执行完的事务,就可以读取到这条数据,否则,还未执行,不可访问。


上面这段话比较绕,但说的比较详细,如果理解的话,那么事务9的执行过程就很清晰了。


在t4时刻,修改用户表的年龄为30:


undolog产生第一条快照数据

id name age db_trx_id db_roll_ptr
1 张三 20 1 null

事务9执行修改操作之后,用户表应为:

id name age db_trx_id db_roll_ptr
1 张三 30 9 0x10010001
2 李四 25 2 null


张三产生回滚地址,当前事务id变化。


t5时刻提交:


事务9生效。


t6时刻再次查询张三的age:


此时拿最后一次执行的事务id-9去ReadView中去m_ids里找,找得到说明时活跃的,没有提交,活跃时不可访问,如果和creator_trx_id比较,相等,说明是自己的操作,可以访问,否则无法访问。如果不在m_ids,说明不再活跃,已提交,不再和当前创建事务id做比较,去和max_trx_id对比,如果db_trx_id大于等于max_trx_id,说明查询的数据在当前事务之后发生改变,无法访问,此时需要通过undolog快照去查找db_trx_id为当前事务id的那条数据,根据undolog表可知,张三的age为20。


这就是MVCC的实现过程,下面用文字来描述下隔离级别的实现:


事务访问数据库时,先判断trx_id是否在m_ids里面


如果在,说明事务是活跃的,继续判断trx_id于ReadView中createor_trx_id的关系

相等,说明当前事务再访问自己的操作,可以访问;


不等,说明当前事务访问的是其他活跃的未提交事务的数据,无法访问。


如果不存在于m_ids中,继续判断trx_id与ReadView中的max_trx_id的关系


若trx_id>=max_trx_id,说明访问的最新的数据是在当前事务后面的操作,无法访问

若trx_id<max_trx_id,说明访问的最新数据是当前事务之前已提交的数据,可以访问


结语


就写到这里吧,关于数据库的数据结构其实还有一些,比如索引,索引的底层B+tree,不过这些东西也很多,准备单独分出来说,咱们下一篇再见。码字不易,觉得还不错,就给个赞吧!

目录
相关文章
|
1天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
14 6
|
1天前
|
SQL 安全 Java
安全问题已经成为软件开发中不可忽视的重要议题。对于使用Java语言开发的应用程序来说,安全性更是至关重要
在当今网络环境下,Java应用的安全性至关重要。本文深入探讨了Java安全编程的最佳实践,包括代码审查、输入验证、输出编码、访问控制和加密技术等,帮助开发者构建安全可靠的应用。通过掌握相关技术和工具,开发者可以有效防范安全威胁,确保应用的安全性。
12 4
|
3天前
|
缓存 监控 Java
如何运用JAVA开发API接口?
本文详细介绍了如何使用Java开发API接口,涵盖创建、实现、测试和部署接口的关键步骤。同时,讨论了接口的安全性设计和设计原则,帮助开发者构建高效、安全、易于维护的API接口。
16 4
|
7天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
8天前
|
SQL Java 程序员
倍增 Java 程序员的开发效率
应用计算困境:Java 作为主流开发语言,在数据处理方面存在复杂度高的问题,而 SQL 虽然简洁但受限于数据库架构。SPL(Structured Process Language)是一种纯 Java 开发的数据处理语言,结合了 Java 的架构灵活性和 SQL 的简洁性。SPL 提供简洁的语法、完善的计算能力、高效的 IDE、大数据支持、与 Java 应用无缝集成以及开放性和热切换特性,能够大幅提升开发效率和性能。
|
2天前
|
安全 Java 测试技术
Java开发必读,谈谈对Spring IOC与AOP的理解
Spring的IOC和AOP机制通过依赖注入和横切关注点的分离,大大提高了代码的模块化和可维护性。IOC使得对象的创建和管理变得灵活可控,降低了对象之间的耦合度;AOP则通过动态代理机制实现了横切关注点的集中管理,减少了重复代码。理解和掌握这两个核心概念,是高效使用Spring框架的关键。希望本文对你深入理解Spring的IOC和AOP有所帮助。
7 0
|
3天前
|
Java API Android开发
kotlin和java开发优缺点
kotlin和java开发优缺点
12 0
WK
|
8天前
|
开发框架 移动开发 Java
C++和Java哪个更适合开发移动应用
本文对比了C++和Java在移动应用开发中的优劣,从市场需求、学习难度、开发效率、跨平台性和应用领域等方面进行了详细分析。Java在Android开发中占据优势,而C++则适合对性能要求较高的场景。选择应根据具体需求和个人偏好综合考虑。
WK
18 0
|
10天前
|
安全 Java
java 中 i++ 到底是否线程安全?
本文通过实例探讨了 `i++` 在多线程环境下的线程安全性问题。首先,使用 100 个线程分别执行 10000 次 `i++` 操作,发现最终结果小于预期的 1000000,证明 `i++` 是线程不安全的。接着,介绍了两种解决方法:使用 `synchronized` 关键字加锁和使用 `AtomicInteger` 类。其中,`AtomicInteger` 通过 `CAS` 操作实现了高效的线程安全。最后,通过分析字节码和源码,解释了 `i++` 为何线程不安全以及 `AtomicInteger` 如何保证线程安全。
java 中 i++ 到底是否线程安全?
|
1天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。