【数据库】数据库基于封锁机制的调度器,使冲突可串行化,保障事务和调度一致性

本文主要是介绍【数据库】数据库基于封锁机制的调度器,使冲突可串行化,保障事务和调度一致性,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

封锁使可串行化

专栏内容

  • 手写数据库toadb
    本专栏主要介绍如何从零开发,开发的步骤,以及开发过程中的涉及的原理,遇到的问题等,让大家能跟上并且可以一起开发,让每个需要的人成为参与者。
    本专栏会定期更新,对应的代码也会定期更新,每个阶段的代码会打上tag,方便阶段学习。

开源贡献

  • toadb开源库

个人主页:我的主页
管理社区:开源数据库
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

文章目录

  • 封锁使可串行化
  • 前言
  • 概述
  • 封锁调度器
  • 两阶段封锁
    • 原理
    • 分析
  • 死锁
  • 总结
  • 结尾

前言

随着信息技术的飞速发展,数据已经渗透到各个领域,成为现代社会最重要的资产之一。在这个大数据时代,数据库理论在数据管理、存储和处理中发挥着至关重要的作用。然而,很多读者可能对数据库理论感到困惑,不知道如何选择合适的数据库,如何设计有效的数据库结构,以及如何处理和管理大量的数据。因此,本专栏旨在为读者提供一套全面、深入的数据库理论指南,帮助他们更好地理解和应用数据库技术。

数据库理论是研究如何有效地管理、存储和检索数据的学科。在现代信息化社会中,数据量呈指数级增长,如何高效地处理和管理这些数据成为一个重要的问题。同时,随着云计算、物联网、大数据等新兴技术的不断发展,数据库理论的重要性日益凸显。

因此,本专栏的分享希望可以提高大家对数据库理论的认识和理解,对于感兴趣的朋友带来帮助。

概述

数据库并发控制,最常用的调度器结构,就是在数据库访问元素上加锁,防止非串行化的行为。

简单来讲,就是事务访问某个元素,先获取它的锁,避免其它事务的非串行化访问。

本文就来介绍这种通过封锁的模式,让调度器产生可串行化动作序列,以及它存在的问题。

在并发编程中,我们会接触到很多类型的系统变量,可以让我们对某一代码区域串行化执行,同样数据库中也会使用这些系统变量来实现数据库中的锁。

使得被锁保护的数据库元素,只能以串行的方式访问,在访问之前获取锁,如果获取不同,只能等待或者中止,获取到锁的就可以进行操作,操作完后释放锁。
在实际的数据库中,会有多种锁的类型,这在以后会进行详细介绍。

对于调度器使用锁时,必须在两种结构上都要保持正确:

  • 事务结构,

一是只有在加锁后,释放锁前,才能进行读写操作;
二是如果加锁了某个元素,那么使用后必须释放锁;

  • 调度结构

同一元素只能被一个事务加锁;而另一尝试加锁事务,要么中止,要么等待;这在不同的数据库实现不一样。

封锁调度器

下图展示了一个封锁的调度器模型架构。
在这里插入图片描述

我们来用一个简单的锁模型介绍一下,假如对于每个数据库元素我们只有一种锁,必须获取锁后才能进行读写,使用完后释放锁。

为了调度器进行决策,调度器有一个锁表,记录了每个数据库元元系的锁状态,如果其上有锁,说明有事务正在使用该数据库元素,其它事务不能访问。

  • 举例如下:
事务T1事务T2数据A数据B
2525
lock(A); read(A);
A = A + 100
write(A); unlock(A);125
lock(A), read(A)
A = A*2
write(A);unlock(A)250
lock(B); read(B);
B = B*2
write(B);unlock(B);50
lock(B); read(B);
B = B + 100
write(B);unlock(B);150

通过这个例子,我们看到一个有趣的现象,虽然调度器已经使事务访问时加了锁,事务对相同的数据库元素也是串行访问,但是最终的调度是不可串行化的,最后状态是不一致的。

说明只是简单封锁,例中的结果不是冲突可串行化的结果。

两阶段封锁

这里介绍一种加锁的条件,叫做两阶段封锁(two-phase locking, 2PL),在这种令人吃惊的条件下,可以保证事务的调度是冲突可串性化的。

原理

两阶段封锁,加解锁需要满足这样的条件:

  • 在每个事务中,所有的封锁请求必须在所有解锁请求之前;

这里就是将事务分为了两个阶段,

  • 第一阶段是封锁阶段,在这个阶段,对需要访问的数据库元素依次加锁;
  • 第二阶段是解锁阶段,这个阶段里,不能再有封锁请求;依次释放锁的过程;

两阶段封锁,像事务一致性一样,对事务中动作顺序进行了限制,符合这一条件的事务,叫做两阶段封锁事务。

  • 举例

那我们再来看上面的例子,将它按2PL进行调度之后:

事务T1事务T2数据A数据B
2525
lock(A); read(A);
A = A + 100
write(A); lock(B); unlock(A);125
lock(A), read(A)
A = A*2
write(A);250
lock(B); 被拒绝
read(B);
B = B + 100
write(B);unlock(B);125
lock(B); unlock(A); read(B);
B = B*2
write(B);unlock(B);250

经过符合2PL条件的调度后,我们可以看到最终结果是符合冲突可串行化的,也就是与两个事务串行执行一样的结果。

分析

两阶段封锁是如何发挥作用的呢?

其实我们仔细观察,就会发现,事务执行的顺序与第一次解锁的顺序是一致的,也就是事务按照解锁的顺序串行在每个数据库元素上执行,这样保证了串行执行的效果,达到了冲突可串行化。

当然严格的可以用归纳法进行证明,这里就不再详述了。

死锁

两阶段封锁虽然可以让事务调度达到冲突可串行化,但是它有一个未解的问题——死锁,也就是调度器迫使几个事务等待另一个事务持有的锁,而该事务又需要等待前几个事务持有的锁。

举例如下:

事务T1事务T2数据A数据B
2525
lock(A); read(A);
lock(B); read(B);
A = A + 100
B = B*2
write(A);125
write(B);50
lock(B) 被拒绝
lock(A) 被拒绝

现在,两个事务都不能继续向下进行,都将永远等待,这将在后面的介绍中继续分享,会对这种问题进行解决。

总结

通过封锁的模式,可以让调度器产生冲突可串行化的调度,但是对于每个事务中涉及多个数据库元素的情况时,又存在死锁的风险。

结尾

非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

这篇关于【数据库】数据库基于封锁机制的调度器,使冲突可串行化,保障事务和调度一致性的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/448534

相关文章

详谈redis跟数据库的数据同步问题

《详谈redis跟数据库的数据同步问题》文章讨论了在Redis和数据库数据一致性问题上的解决方案,主要比较了先更新Redis缓存再更新数据库和先更新数据库再更新Redis缓存两种方案,文章指出,删除R... 目录一、Redis 数据库数据一致性的解决方案1.1、更新Redis缓存、删除Redis缓存的区别二

oracle数据库索引失效的问题及解决

《oracle数据库索引失效的问题及解决》本文总结了在Oracle数据库中索引失效的一些常见场景,包括使用isnull、isnotnull、!=、、、函数处理、like前置%查询以及范围索引和等值索引... 目录oracle数据库索引失效问题场景环境索引失效情况及验证结论一结论二结论三结论四结论五总结ora

Redis事务与数据持久化方式

《Redis事务与数据持久化方式》该文档主要介绍了Redis事务和持久化机制,事务通过将多个命令打包执行,而持久化则通过快照(RDB)和追加式文件(AOF)两种方式将内存数据保存到磁盘,以防止数据丢失... 目录一、Redis 事务1.1 事务本质1.2 数据库事务与redis事务1.2.1 数据库事务1.

C#实现文件读写到SQLite数据库

《C#实现文件读写到SQLite数据库》这篇文章主要为大家详细介绍了使用C#将文件读写到SQLite数据库的几种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以参考一下... 目录1. 使用 BLOB 存储文件2. 存储文件路径3. 分块存储文件《文件读写到SQLite数据库China编程的方法》博客中,介绍了文

Android数据库Room的实际使用过程总结

《Android数据库Room的实际使用过程总结》这篇文章主要给大家介绍了关于Android数据库Room的实际使用过程,详细介绍了如何创建实体类、数据访问对象(DAO)和数据库抽象类,需要的朋友可以... 目录前言一、Room的基本使用1.项目配置2.创建实体类(Entity)3.创建数据访问对象(DAO

Spring使用@Retryable实现自动重试机制

《Spring使用@Retryable实现自动重试机制》在微服务架构中,服务之间的调用可能会因为一些暂时性的错误而失败,例如网络波动、数据库连接超时或第三方服务不可用等,在本文中,我们将介绍如何在Sp... 目录引言1. 什么是 @Retryable?2. 如何在 Spring 中使用 @Retryable

SQL Server数据库磁盘满了的解决办法

《SQLServer数据库磁盘满了的解决办法》系统再正常运行,我还在操作中,突然发现接口报错,后续所有接口都报错了,一查日志发现说是数据库磁盘满了,所以本文记录了SQLServer数据库磁盘满了的解... 目录问题解决方法删除数据库日志设置数据库日志大小问题今http://www.chinasem.cn天发

SpringBoot嵌套事务详解及失效解决方案

《SpringBoot嵌套事务详解及失效解决方案》在复杂的业务场景中,嵌套事务可以帮助我们更加精细地控制数据的一致性,然而,在SpringBoot中,如果嵌套事务的配置不当,可能会导致事务不生效的问题... 目录什么是嵌套事务?嵌套事务失效的原因核心问题:嵌套事务的解决方案方案一:将嵌套事务方法提取到独立类

Oracle数据库执行计划的查看与分析技巧

《Oracle数据库执行计划的查看与分析技巧》在Oracle数据库中,执行计划能够帮助我们深入了解SQL语句在数据库内部的执行细节,进而优化查询性能、提升系统效率,执行计划是Oracle数据库优化器为... 目录一、什么是执行计划二、查看执行计划的方法(一)使用 EXPLAIN PLAN 命令(二)通过 S

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization