当前位置: 首页 > news >正文

个人备案网站放什么手续曹健的wordpress博客

个人备案网站放什么手续,曹健的wordpress博客,大兴网站制作,wordpress数据库太大简介#xff1a; 在巍峨的数据库大厦体系中#xff0c;查询优化器和事务体系是两堵重要的承重墙#xff0c;二者是如此重要以至于整个数据库体系结构设计中大量的数据结构、机制和特性都是围绕着二者搭建起来的。他们一个负责如何更快的查询到数据#xff0c;更有效的组织起…简介 在巍峨的数据库大厦体系中查询优化器和事务体系是两堵重要的承重墙二者是如此重要以至于整个数据库体系结构设计中大量的数据结构、机制和特性都是围绕着二者搭建起来的。他们一个负责如何更快的查询到数据更有效的组织起底层数据体系一个负责安全、稳定、持久的存储数据为用户的读写并发提供逻辑实现。我们今天探索的主题是事务体系然而事务体系太过庞大我们需要分成若干次的内容。本文就针对PolarDB事务体系中的原子性进行剖析。 作者 | 佑熙 来源 | 阿里技术公众号 一 前言 在巍峨的数据库大厦体系中查询优化器和事务体系是两堵重要的承重墙二者是如此重要以至于整个数据库体系结构设计中大量的数据结构、机制和特性都是围绕着二者搭建起来的。他们一个负责如何更快的查询到数据更有效的组织起底层数据体系一个负责安全、稳定、持久的存储数据为用户的读写并发提供逻辑实现。我们今天探索的主题是事务体系然而事务体系太过庞大我们需要分成若干次的内容。本文就针对PolarDB事务体系中的原子性进行剖析。 二 问题 在阅读本文之前首先提出几个重要的问题这几个问题或许在接触数据库之前你也曾经疑惑过。但是曾经这些问题的答案可能只是简单的被诸如“预写日志”“崩溃恢复机制”等简单的答案回答过了本文希望能够更深一步的讨论这些机制的实现及内在原理。 数据库原子性到底是如何保证的使用了哪些特殊的数据结构为什么要用为什么我写入成功的数据能够被保证不丢失为什么数据库崩溃后可以完整的恢复出来逻辑上我已经提交的数据更进一步什么是逻辑上已提交的数据哪一个步骤才算是真正的提交 三 背景 1 原子性在ACID中的位置 大名鼎鼎的ACID特性被提出后这个概念不断的被引用最初被写入SQL92标准这四种特性可以大概概括出人们心中对于数据库最核心的诉求。本文要讲的原子性便是其中第一个特性我们先关注原子性在事务ACID中的位置。 这是个人对于数据库ACID特性关系的理解我认为数据库ACID特性其实可以分为两个视角去定义其中AID原子、持久、隔离特性是从事务本身的视角去定义而C一致特性是从用户的视角去定义。下面我会分别谈下自己的理解。 原子性我们还是从这些特性的概念出发去讨论原子性的概念是一个事务要么执行成功要么执行失败即All or nothing。这种特质我们可以用一个最小的事务模型去定义出来我们假设有一个事务我们通过一套机制能够实现它真正的提交或回滚这个目的就达成了用户只是通过我们的系统进行了一次提交而原子性的重心不在于事务成功或失败本身而是保证了事务体系只接受成功或失败两种状态而且有相应的策略来保证成功或失败的物理结果和逻辑结果是一致的。原子性可以通过最小事务单元的特性定义出来是整个事务体系的基石。持久性而持久性指的是事务一旦提交后就可以永久的保存在数据库中。持久性的范围与视角几乎与原子性是一致的其实也导致了二者在概念和实现上也是紧密相连的。二者都一定意义上保证了数据的一致和可恢复性而界限便是事务提交的时刻。举例来说一个数据目前的状态是T如果某个事务A试图将状态更新到T1如果这个事务A失败了那么数据库状态回到T这是原子性保证的如果事务A提交成功了那么事务状态变成T1的那一刻这个是原子性保证的而一旦事务状态变成T1且事务成功提交事务已经结束不再存在原子性这个T1的状态就是由持久性负责保证。从这个角度可以推断原子性保证了事务提交前数据的崩溃恢复而持久性保证了事务提交后的崩溃恢复。隔离性隔离性同样是定义在事务层面的一个机制给事务并发提供了某种程度的隔离保证。隔离性的本质是防止事务并发会导致不一致的状态。由于不是本文的重点这里不做详述。一致性相较于其他几个特性很特殊一致性的概念是数据库在经过一个或多个事务后数据库必须保持在一致性的状态。如果从事务的角度去理解保证了AID就可以保证事务是可串行、可恢复、原子性的但是这种事务状态的一致性就是真正的一致性吗破坏了AID就一定破坏C但是反之AID都保证了C一定会被保证吗如果答案是是的话那这个概念就会失去它的意义。我们可以保证AID来保证事务是一致的但是是否能够证明事务的一致一定保证数据的一致呢另外数据一致这个概念通过事务很难去准确定义而如果通过用户层面就很好定义。数据一致就是用户认为数据库中数据任何时候的状态是满足其业务逻辑的。比如银行存款不能是负数所以用户定义了一个非负约束。我认为这是概念设计者的一个留白倾向于将一致性视为一种高阶目标。 本文主要还是围绕原子性进行而中间涉及到崩溃恢复的话题可能会涉及到持久性。隔离性和一致性本文不讨论在可见性的部分我们默认数据库具有完成的隔离性即可串行化的隔离级别。 2 原子性的内在要求 上面讲了很多对于数据库事务特性的理解下面进入我们的主题原子性。我们还是需要拿刚才的例子来继续阐述原子性。目前数据库的状态是T现在希望通过一个事务A将数据状态升级为T1。我们讨论这个过程的原子性。 如果我们要保证这个事务是原子的那么我们可以定义三个要求只有满足了下者才可以说这个事务是原子性的 数据库存在一个事务真正成功提交的时间点。在这个时间点之前开启的事务或者获取的快照只应该看到T状态这个时间点之后开启的事务或者获取的快照只应该看到T1状态。在这个时间点之前任何时候的崩溃数据库都应该能够回到T状态在这个时间点之后任何时候崩溃数据库都应该能回到T1状态。 注意这个时间点我们并没有定义出来甚至我们都不能确定2/3中的这个时间点是不是同一个时间点。我们能确定的是这个时间点一定存在否则就没办法说事务是原子性的原子性确定了提交/回滚必须有一个确定的时间点。另外根据我们刚才的描述可以推测出2中的时间点我们可以定义为原子性位点。由于原子性位点之前的提交我们不可见之后可见那么这个原子性位点对于数据库中其他事务来说就是该事务提交的时间点而3中的位点可以定位为持久性位点由于这符合持久性对于崩溃恢复的定义。即对于持久性来说3这个位点后事务已经提交了。 四 原子性方案讨论 1 从两种简单的方案说起 首先我们从两个简单的方案来谈起原子性这一步的目的是试图说明为什么我们接下来每一步介绍的数据结构都是为了实现原子性必不可少的。 简单Direct IO 设想我们存在这样一个数据库每次用户操作都会把数据写到磁盘中。我们把这种方式叫做简单Direct IO简单的意思是指我们没有记录任何数据日志而只记录了数据本身。假设初始的数据版本是T这样当我们插入了一些数据之后如果发生了数据崩溃磁盘上会写着一个T0.5版本的数据页并且我们没有任何办法去回滚或继续进行后续的操作。这样失败的CASE无疑打破了原子性因为目前的状态既不是提交也不是回滚而是一个介于中间的状态所以这是一次失败的尝试。 简单Buffer IO 接下来我们有了一种新的方案这种方案叫做简单Buffer IO。同样我们没有日志但是我们加入了一个新的数据结构叫做“共享缓存池”。这样当我们每次写数据页的时候并不是直接把数据写到数据库上而是写到了shared buffer pool 中这样会有显而易见的优势首先读写效率会大大的提高我们每次写都不必等待数据页真实的写入磁盘而可以异步的进行其次如果数据库在事务未提交前回滚或者崩溃掉了我们只需要丢弃掉shared buffer pool中的数据只有当数据库成功提交时它才可以真正的把数据刷到磁盘上这样从可见性和崩溃恢复性上看我们看似已经满足了要求。 但是上述方案还是有一个难以解决的问题即数据落盘这件事并不像我们想象的这么简单。比如shared buffer pool中有10个脏页我们可以通过存储技术来保证单个页面的刷盘是原子的但是在这10个页面的中间任何时候数据库都可能崩溃。继而不论我们何时决定数据落盘只要数据落盘的过程中机器发生了崩溃这个数据都可能在磁盘上产生一个T0.5的版本并且我们在重启后还是没办法去重做或者回滚。 上面两个例子的阐述似乎注定了数据库没有办法通过不依赖其他结构的情况下保证数据的一致性还有一种流行的方案是SQLite数据库的Shadow Paging技术这里不讨论所以如果想解决这些问题我们需要引入下一个重要的数据结构数据日志。 2 预写日志 Buffer IO方案 方案总览 我们在Buffer IO的基础上引入了数据日志这样的数据结构用来解决数据不一致的问题。 在数据缓存的部分与之前的想法一样不同的是我们在写数据之前会额外记录一个xlog buffer。这些xlog buffer是一个有序列的日志他的序列号被称为lsn我们会把这个数据对应的日志lsn记录在数据页面上。每一个数据页页面都记录了更新它最新的日志序号。这一特性是为了保证日志与数据的一致性。 设想一下如果我们能够引入的日志与数据版本是完全一致的并且保证数据日志先于日志持久化那么不论何时数据崩溃我们都可以通过这个一致的日志页恢复出来。这样就可以解决之前说的数据崩溃问题。不论事务提交前或者提交后崩溃我们都可以通过回放日志的方案来回放出正确的数据版本这样就可以实现崩溃恢复的原子性。另外关于可见性的部分我们可以通过多版本快照的方式实现。保证数据日志和数据一致并不容易下面我们详细讲下如何保证还有崩溃时数据如何恢复。 事务提交与控制刷脏 WAL日志被设计出来的目的是为了保证数据的可恢复性而为了保证WAL日志与数据的一致性当数据缓存被持久化到磁盘时持久化的数据页对应的WAL日志必须先一步被持久化到磁盘中这句话阐述了控制刷脏的本质含义。 数据库后台存在这样一个进程叫做checkpoint进程其周期性的进行checkpoint操作。当checkpoint发生的时候它会向xlog日志中写入一条checkpoint日志这条checkpoint日志包含了当前的REDO位点。checkpoint保证了当前所有脏数据已经被刷到了磁盘当中。进行第一次插入操作此时共享内存找不到这个页面它会把这个页面从磁盘加载到共享内存中之后写入本次插入的输入并且插入一条写数据的xlog到xlog buffer中将这个表的日志标记从LSN0升级到LSN1。在事务提交的时刻事务会写入一条事务提交日志之后wal buffer pool上所有本次事务提交的WAL日志会一并被刷到磁盘上。之后插入第二条数据B他会插入一条写数据的xlog到xlog buffer中将这个表的日志标记从LSN1升级到LSN2。同3一样的操作。 之后如果数据库正常运行接下来的bgwriter/checkpoint进程会把数据页异步的刷到磁盘上而一旦数据库发生崩溃由于A、B两条日志对应的数据日志与事务提交日志都已经被刷到了磁盘上所以可以通过日志回放在shared buffer pool中重新回放出这些数据之后异步写入磁盘。 fullpage机制保证可恢复性 WAL日志的恢复似乎是完美无缺的但不幸的是刚才的方案还是存在一些瑕疵。设想当一个bgwriter进程在异步的写数据时遇到了数据库的CRASH这时一部分脏页写到了磁盘上磁盘上可能存在坏页。PolarDB数据页是8k极端情况下磁盘的4k写是有可能写出坏页面的然而WAL日志是没办法在坏页上回放数据的。这时就需要用到另外一个机制来保证极端情况下数据库能够找到原始数据这就涉及到了一个重要的机制fullpage机制。 在每一个checkpoin动作之后的第一次修改数据时PolarDB会将这条修改的数据连同整个数据页写入到wal buffer中之后再刷入磁盘这种包含整个数据页的WAL日志被称为备份块。备份块的存在使得在任何情况下WAL日志都可以将完整的数据页给回放出来。下面是一个完整的过程。 checkpoint动作进行第一次插入操作此时共享内存找不到这个页面它会把这个页面从磁盘加载到共享内存中之后写入本次插入的输入。这时不同于上一节的操作PolarDB序号为LSN1的这条WAL日志会把从磁盘上读上来标记为LSN 0的整个页面写入到wal buffer pool中。事务提交此时整个WAL日志被强制刷入磁盘上的WAL段中。同上节同上节 这时如果数据库发生了崩溃在数据库重新拉起恢复时一旦它遇到了坏掉的页面便可以通过最初的WAL日志中记录的最初版本的页面一步一步的把正确的数据给回放出来。 基于WAL日志的崩溃恢复机制 有了前两节的基础上我们可以继续演示如果数据库崩溃后数据是如何被回放出来的。我们演示一种数据页被写坏的回放。 当数据库回放到写入数据A的这条WAL日志时它会从磁盘中读出TABLE A这个页面。这里的这条WAL日志是一条备份日志这是由于CHECKPOINT后每个回放页面的第一条WAL日志都是备份日志。当这条日志被回放时备份日志有特殊的回放规则它总是将自己页面覆盖掉原来的页面并将原来页面的LSN升级为这个页面的LSN。为了保证数据一致性正常回放页面只会回放大于自己LSN号码的WAL日志。在这个例子中由于备份块的存在写坏的页面被成功恢复了出来。接下来PolarDB会按照正常的回放规则去回放后续的日志。 最后数据回放成功后shared buffer pool中的数据便可以异步的被刷到磁盘上去替换之前损坏的数据。 我们花了很大的篇幅来说明数据库是如何通过预写日志而进行崩溃恢复的这似乎可以解释持久性位点的含义下面我我们还需要再解释可见性的问题。 3 可见性机制 由于我们对于原子性的说明中会涉及可见性的概念这个概念在PolarDB中由一套复杂的MVCC机制来实现且大多属于隔离性的范畴。这里会对可见性进行一个简单的说明而更详细的说明会放到隔离性的文章中继续阐述。 事务元组 第一个要说到的是事务元组。他是一条数据的最小单元真正存放了数据这里我们只关注几个字段就好了。 t_xmin生成该数据的事务IDt_xmax修改该事务数据的事务ID删除或锁定数据的事务IDt_cid同一事务中对该元组操作的一个序号t_ctid一个由段号/偏移量组成的指针指向最新版本的数据 快照 第二个要说到的是快照。快照记录了某一个时间点数据库中事务的状态。 关于快照我们依旧不展开我们知道通过快照可以从procArray中获取到某一个时间点数据库中所有可能事务的状态即可。 当前事务状态 第三点要说的到的是当前事务状态事务状态是指数据库中决定事务运行状态的的机制。在并发的环境中决定看到的事务状态是非常重要的一件事。 在查看一个tuple中的事务状态时可能会涉及到三个数据结构t_infomask、procArray、clog infomask位于tuple头部的缓存标志位标志了该元组xmin/xmax两个事务的运行状态这个状态可以看作是clog的一层异步缓存用来加速事务状态的获取其状态设置是异步设置在事务提交时并不将所有事务相关的元组都立即升级而是等待当第一个足够新的能够看到本次更新的快照设置时再去设置。procArray快照快照中的事务状态快照的获取实际上就是在procArray中拿到这一瞬间数据库中所有事务的状态快照一旦获取状态恒定除非再次获取同一事务中获取内容是否改变取决于事务隔离级别。clog事务的实际状态分为clog buffer和clog文件两部分。clog buffer中实时的记录了所有的事务状态。 在一个可见性判断过程中三者访问的顺序是[infomask - 快照clog]而三者的决定性顺序是[快照 - clog - infomask] 。 infomask是最容易获取的信息就记录在元组的头部在部分条件下通过infomask就可以明确当前事务的可见性不需要涉及到后面的数据结构快照拥有最高级的决定权最终决定xmin/xmax事务的状态是运行/未运行而clog用来辅助可见性的判断并且辅助设置infomask的值。举例而言如果这个判断xmin事务可见性时发现在快照/clog中都已经提交那么会把t_infomask置为已提交而如果xmin事务可见性时发现在快照提交而clog未提交则系统判断发生了崩溃或回滚将infomask设置为事务非法。 事务快照可见性 在介绍元组和快照后我们就可以继续讨论快照可见性的话题。PolarDB的可见性有一套复杂的定义体系需要通过许多信息组合定义出来但是其中最直接的就是快照和元组头。下面通过一个数据插入和更新的示例来说明元组头和快照的可见性。 本文不讨论隔离性我们假设隔离级别是可串行化 Snapshot1时刻此时事务1184/1187都未开始元组中也没有记录student表是一张空表通过Snapshot1快照可以得到的数据是空我们把这个版本记做T。Snapshot1 - Snapshot2时此刻我们获取快照那么拿到的还是Snapshot1那么他看到的数据应该还是T。Snapshot2时刻此时事务1184已经结束1187还未开始。所以1184的修改对用户可见1187仍旧不可见。具体到元组中可以看到 (1184/0) 这样的元组头所以看到的是数据版本Tom我们把这个版本记做T1。Snapshot2 - Snapshot3时此刻我们获取快照那么拿到的还是Snapshot2那么他看到的数据应该还是T1。Snapshot3时刻此刻事务1184/1187都已经结束二者都可见所以我们可以看到元组中(11841187)和11871187二者都不可见而11870即Susan是可见的。我们把这个版本记做T2。 通过上述分析我们可以得到一个简单的结论数据库的可见性取决于快照的时机。我们原子性中所谓的可见性版本不同其实是指拿到的快照不同快照决定了一个正在执行中的事务是否已经提交。这种提交与事务标记提交状态甚至是记录clog提交都没有关系我们可以通过这种方法来使得我们拿到的快照与事务提交具有一致性。 事务原子性中的可见性 上文中我们已经简述了PolarDB快照可见性的问题这里补充下事务提交时的具体实现问题。 我们设计可见性机制的核心思想是“事务只应该看到它应该看到的数据版本”。如何定义应该看到这里只举一个简单的例子如果一个元组的xmin事务没有提交其他事务大概率是看不到的而如果一个元组的xmin事务已经提交其他事务就可能会看到。如何知道这个xmin有没有提交上文已经提到了我们通过快照来决定所以我们事务提交时的关键机制就是新快照的更新机制。 可见性在事务提交时涉及到两个重要的数据结构clog buffer和procArray 。二者的关系在上文已经给出了解释他们在判断事务可见性时发挥一定的作用当然procArray起到了决定性的作用。这是因为快照的获取实际上就是一个遍历ProcArray的过程。 在实际第三步会将本事务提交的信息写入clog buffer此时事务标记clog是已提交但实际上仍旧没有提交。之后事务标记ProcArray已提交这一步事务完成了真正的提交这个时间点之后重新获取的快照会更新数据版本。 五 PolarDB 中原子性的实现 在完成了PolarDB崩溃恢复及可见性理论的说明之后我们可以知道PolarDB可以通过这样一套预写日志BufferIO的方案来保证事务的崩溃恢复和可见一致性从而实现原子性。下面我们将针对事务提交中最重要的环节进行探究找出我们最初提到的原子性位点到底指什么。 1 事务崩溃恢复一致——持久性位点 简单来说事务提交中有这样四个操作对于事务的原子性来说是最为核心和重要的。本节我们先考虑前两个操作。 提交事务的Commit日志即Commit 的WAL日志。将本次事务所有的提交的WAL日志全部强制刷盘持久化到存储。 我们标记这个xlogWAL日志落盘的位点我们设想两种情况 如果在这个位点前事务崩溃或者回滚了那么不管数据日志有没有刷盘Commit日志一定没有刷盘由于WAL日志具有顺序性Commit日志一定是最后一个持久化到磁盘中。此时如果我们对数据进行回放我们发现缺少Commit日志的事务无法被标记为已提交状态而根据可见性这种状态相关的数据一定是不可见。这些数据之后会被视为脏数据给清理掉。所以我们可以得出结论在这个节点前崩溃事务实际上就是没有提交。数据库实质上是恢复到了状态T。如果在这个位点后崩溃或回滚了此时我们不论它在哪一步崩溃或回滚我们都可以确定Commit日志一定刷到了磁盘上。而一旦Commit日志被刷到了磁盘上那么这个事务所写的数据一定可以被回放出来且标记为已提交。那么这个数据就是可见的。这个事务实际上已经提交了数据库被恢复到了T1。 这个现象表明2号位点似乎就是崩溃恢复的临界点它标注了数据库崩溃恢复可以回到T或者T1状态。那么我们如何称呼这个位点回想持久性的概念事务一旦提交该事务对于数据库的修改就永久的保留在了数据库中。二者实际上是吻合的。所以我们将这个2号位点称为持久性位点。 另外关于xlog刷盘还有一点需要说明的是xlog刷盘和回放具有单个文件的原子性WAL日志头部的CRC校验提供了单个WAL日志文件的合法性校验如果WAL日志写磁盘损坏这条WAL日志的内容无效确保不会出现数据的部分回放。 2 事务的可见性一致——原子性位点 接下来我们继续看3、4号操作 将本次事务提交写入到Clog buffer中。将本次事务提交的结果写入到ProcArray中。 3号操作是在Clog buffer中记录了事务的当前状态可以看作是一层日志缓存。4号操作将提交操作写入到了ProcArray中这是非常重要的一步操作通过刚才的说明我们知道快照判断事务状态是通过ProcArray进行的。即这一步决定了其他事务看到的该事务状态。 如果在4号操作前事务崩溃或回滚那么数据库中所有其他事务看到的数据版本都是T相当于事务没有真正的提交。这个判断即通过可见性 - 快照 - Procarray这个顺序决定的。 而当4号操作后针对所有观察者来说这个事务已经提交了因为所有在这个时间点之后拿到的快照数据版本都是T1。 从这一点考虑4号操作完全切合原子性操作的含义。因为4号操作的进行与否影响了事务能否成功提交。4号操作前事务总是允许回滚的因为没有其他事务看到该事务的T1状态但是4号操作过后事务便不允许回滚不然一旦存在读到T1版本的其他事务就会造成数据的不一致。而原子性的概念即是事务成功提交或失败回滚。由于4号操作后不允许回滚那4号操作就完全可以作为事务成功提交的标志。 综上所述我们可以将4号操作定义为事务的原子性位点。 3 持久性位点与原子性位点 原子性与持久性的要求 再次给出原子性与持久性的概念 原子性一个事务要么执行成功要么执行失败。持久性一个事务一旦执行成功就可以永久的保存在数据库中。 我们把4号操作标记为原子性位点是因为在4号操作的时刻客观上所有的观察者都认为这个事务已经提交了快照的版本从T升级为T1事务不再可回滚。那么事务一旦提交原子性是否就不生效了我认为是的原子性至多只保证事务成功提交那一刻的数据一致性事务已经结束了我们就没办法再说原子性。所以原子性在原子性位点前保证了事务的可见、可恢复。 我们把2号位点标记为持久性位点是因为持久性认为事务成功后就可以永久的保留。根据上述的推测这个位点无疑就是2号这个持久性位点。所以从2号位点开始后的所有时间我们都应该保证持久性。 如何理解两个位点 在解释完2、4号两个位点之后我们最终可以把事务提交时涉及到的两个最重要概念定义出来我们现在可以回答第一个问题到底在哪个时刻事务真正的提交答案是持久性位点后事务可以被完整的恢复出来而原子性位点后事务真正的被其他事务视作提交。但是二者却并不是分离性的这如何理解呢 我认为这其实是原子性实现的一种妥协因为我们没有必要把二者统一我们只需要保证关键性的一点只要两个位点的顺序能够使得在不同状态下的数据具有一致性那么就可以认为它符合我们原子性的定义。 在持久性位点前崩溃或回滚此时事务失败崩溃前或恢复后数据版本都是T。在持久性位点后原子性位点间崩溃或回滚此时事务的可见性版本是T也就是说对于数据库中的所有事务来说我们看到的都是T。回滚后数据被重新回放到了T1而此时数据库重启后会发现在数据库崩溃前的事务拿到快照看到的数据版本是T崩溃后重启拿到快照看到的数据版本是T1仿佛事务被隐式的提交了。但是这并不违背数据的一致性。在原子位点后崩溃。这个事务已经提交了崩溃前崩溃后事务看到的都是T1版本的数据。 最后我们考虑两个位点为什么没有选择合并。持久性位点的操作是WAL日志的刷盘这个涉及到了磁盘IO的问题另一方面原子性位点做的事情是写ProcArray这就要拿到ProcArray上的一把争抢很严重的大锁可以认为是一次高频的共享内存写行为二者本身都关乎数据库事务的效率如果绑定了二者成为一个原子操作无疑会使得二者等待相当严重可能会对事务的运行效率造成较大影响。从这个角度来说二者的行为分离是一个效率上的考虑。 二者顺序是否可以颠倒 显然不可以通过上述的示意图我们可以看到中间这一段时间可能出现既不满足原子性要求也不满足持久性要求的区域。 具体而言如果先进行原子性位点再进行持久性位点则设想二者中间崩溃的事务情形。其他事务在崩溃前会看到T1版本的数据崩溃后看到了T版本的数据这样看到未来数据的行为显然是不被允许的。 如何定义真正的提交 真正的提交就是原子性位点提交。 还是最基本的道理真正提交的标志就是数据版本从T升级为T1。这个位点就是原子性位点。在这个点之前其他事务看到的数据版本都是T说真正的提交是不恰当的在这个点之后事务无法被回滚。这足以说明这就是事务真正的提交点。 其他操作 我们最后关注1/3号操作 1号操作是写wal commit日志到xlog buffer这个写日志对于事务提交来说并不关键因为如果它写入了没有刷到磁盘上那么它其实还是毫无作用。3号操作是在clog buffer 中标记本事务为已提交状态这个操作对事务提交来说也不关键。因为如果数据库运行正常它不影响本事务快照的可见性如果数据库崩溃这个clog状态不论是否已经持久化事务状态都可以被xlog中的 Commmit/Abort日志给回放出来。 六 PolarDB的原子性过程 1 事务提交 本节我们回到事务提交函数中看到这几个操作在函数调用栈中的位置。 事务提交流程是带有事务ID的事务不带事务ID的事务没有这个过程。由于不带事务ID的事务大概率是只读操作不会对数据库中数据一致性造成任何影响。提交xlog前会开启严格模式这个模式下任何错误都会是致命错误数据库直接崩溃重启。xlog刷盘和CLOG写内存的顺序是在同步模式下进行的异步模式下不保证xlog刷盘所以可能会崩溃后丢失数据。3/4中间有一步关键的操作Replication等待。实际上此时数据xlog已经刷盘但是还没有真正的提交在同步模式下主库会等待被库将刷到磁盘上的xlog应用完毕之后再进行下一步。写ProcArray本事务提交事务真正提交完成事务不再可回滚。清理资源状态此时工作已和本事务没有任何关系。 2 事务回滚 没有事务ID的事务回滚会直接跳过。回滚前会首先判断事务是否已提交这个判断是基于CLOG进行的。一个事务怎么能又提交又回滚呢这就是我们之前讨论的3-4之间的状态如果CLOG记录了提交那么遇到回滚命令数据库直接发生致命故障崩溃重启。回滚中也会相应的写入xlog回滚日志不过是异步刷到磁盘。可以设想其实回滚日志即使不写入数据也是不可见的。当事务在ProcArray中写入回滚日志后事务在进程中真正的回滚了其实这个状态对其他事务没有影响之前后拿到的数据版本都是T。 七 总结与展望 最后对全文做一个总结本文主要围绕着“如何实现事务原子性”这个话题展开分别从数据库的崩溃恢复特性和事务可见性来说明了PolarDB数据库实现原子性的底层原理。在介绍预写日志buffer IO原理的过程中还谈到了shared buffer、WAL日志、clog、ProcArray、这些对原子性来说重要的数据结构。在事务这个整体下数据库的各个模块巧妙的搭接起来充分利用磁盘、缓存、IO这些计算机资源组成了一套完整的数据库系统。 联想到计算机科学其他的模型如ISO网络模型中传输层TCP协议在一个不可靠的信道上提供可靠的通信服务。数据库事务实现了类似的思想即在一个不可靠的操作系统随时可能崩溃和磁盘存储无法大量数据的原子写上可靠的存储数据。这一简单而重要的思想可谓是数据库系统的基石它如此重要以至于整个数据库中最核心的数据结构大多其有关。或许随着数据库的发展未来技术更迭出更先进的数据库架构体系但是我们不能忘记是原子性、持久性仍旧应当是数据库设计的核心。 八 思考 到这里事务原子性的重点就结束了最后针对本文提到的观点留下几个问题供大家思考。 如何理解事务提交的原子性和持久性位点思考单个事务原子性和多个事务原子性的关系崩溃恢复和可见性是否是一体的PolarDB中存在异步提交的概念即不要求事务提交时不要求xlog日志落盘。请思考在这个模式下可能违背事务的哪些特性是否违背原子性和持久性 参考资料https://www.interdb.jp/pg/ 原文链接 本文为阿里云原创内容未经允许不得转载。
http://www.zqtcl.cn/news/232304/

相关文章:

  • 产品网站建设框架wordpress用户名密码加密方式
  • 入侵dedecms网站管理员密码青岛seo整站优化公司
  • 小网站备案南宁网站建设排名
  • 西安免费做网站wordpress 使用方法
  • 企业营销的意义优化核心系列网站
  • 微信网站设计一起做网站17广州
  • 重庆网络推广网站如何制作app演示视频
  • 网站logo是指手机上做app的软件
  • 做母婴育儿类网站好做seo排名吗深圳网站. 方维网络
  • 小型装修公司店面装修windows优化大师会员
  • php服装商城网站建设wordpress主题去除友情链接
  • 北京网站设计公司sx成都柚米科技15福建众利建设工程网站
  • 深圳大型网站建设服务公司wordpress后台为什么这么慢
  • 信用网站建设工作简报青岛的建筑公司
  • 网站怎么做文件上传灯饰 东莞网站建设
  • 建设电子商务网站的规划书电子商务平台网站模板
  • 桂林网站建设 腾云安康养老院收费
  • 网站建设找酷风旅游手机网站开发
  • 宜昌建设厅网站开发公司起名大全
  • 龙口建设局网站深圳十大网站建设公司
  • 湛江网站设计哪家好公司网址怎么查询
  • 网站怎么设置关键词河南宣传片制作公司
  • 做网站 怎么赚钱吗安乡网站制作
  • 国外展览展示设计网站沧州网络推广管理公司
  • 物流信息平台网站建设深圳做手机网站建设
  • 品牌型网站的特点领导视察网站建设
  • 如何自己做网站推广淘宝客佛山小程序开发公司
  • 天津市建设局网站口碑营销相关案例
  • 怎么有自己的网站厂字形网页布局网站
  • 广州市财贸建设开发监理网站工程建设企业等采用