文章目录
概述
- 【理解的关键】串行化
另外说说对于隔离级别的理解:
- 不同场景下, 一致性需求不同.
- 造成不一致性的因素:
并发,回滚等数据库操作.
- 对一致性的不同分类的处理,导致了 不同的隔离级别.
为什么要进行并发控制
并发意味着多个流程,以某种不确定的方式进行交替执行。这种交替的不确定性,往往会对结果造成相应的不确定性。
站在组合的角度来看这种交替,其可能产生的并发组合方案,是非常多的。然而,在这些组合方案空间中,有一些是不影响逻辑(人们根据各自需求定义的)正确性,而另外一些则是造成结果的混乱,不合逻辑。
所以,并发控制的目的,在于在多个流程并发执行的过程中,通过控制某些关键的并发结点,使得并发执行只保留可能正确的并发组合方案。
【多线程角度】简单的例子,从java多线程角度进行论述,多个线程操作同一个变量,如果并发推进的顺序不够正确,造成的结果是,可能是某个线程对于变量操作的丢失。
现在让我们回到数据库上来理解,数据库中的表格、记录,可以看作是java多线程中操作的变量,只不过数据库中的这些变量是存储在硬盘上的,一般是被批量操作的,并且具有一些从数据库中获得的性质(比如,回滚的性质)。
举个简单的例子说明数据库中存在的现象:
- 多个售票系统,可以类比成多个线程(这样类比是为了方便理解)。它们共同操作着数据库中的变量,或者读或者写,这其中必然会存在多个系统的共享,包括对于同一个表的共享、对于同一个表中同一个记录的共享。
- 【假设】为了理解并发控制的重要性,我们最好先站在其对立面来看看这个场景,即如果没有并发控制,会发生什么?没有并发控制,意味着并发方案中,哪一种组合都是有可能的,包括那些错误的方案。比如,有两个售票系统A、B,A系统和B系统同时操作数据库记录C(座位),A系统读取了C,B系统读取了C,然后双方都认为C座位未售出,然后就可能发生一票多卖的情况。
三种典型的不一致
而在数据库中,通常存在会出现哪些错误呢?
下面列举了数据库中存在的几种典型的问题,更具体一点,即数据的不一致性。
- T1,T2表示两个不同的事务。(可以类比于java中的两个不同的线程)
- 【交替执行】T1与T2是交替执行的。而在下面这些并发组合方案中,产生了如下3类不一致的问题。
- 【不一致】这些说的不一致,是指(1)不同事务操作的数据是不一致的;(2)或者同一个事务前后不一致。
- 【丢失修改】简单例子,对于A的操作(如加、减),在事务交替过程中,某个事务的某些操作表现为并未成功。
- 【不能重复读】在一个事务的不同阶段,读取出来的内容是不同的;见示意图。
出现这种情况,意味着整个事务的不可靠.尽管这种不一致是由外界所导致的. -->
所以需要与其它外界之间由一定的契约,即所谓的封锁协议;
- 【脏读】数据库回滚的特性(回滚是为了满足事务特性:持久化),这同时也就引入了脏读。
引入并发控制
并发控制及相应的事务处理技术是DBMS的核心技术:
什么是事务
事务的基本概念
- 【事务概念服务的目的】维护数据库一致性的概念工具。(当然,后面还会提出一些特性及细节,以保证其能够确保数据库的一致性)
- 【事务的应用】事务在具体程序中的应用,应该是由程序员来决定的,决定哪些对于数据库的操作应该放到同一事务中(意味着满足事务的ACID特性)。下面银行的例子就说明了这一点,一些事情必须同时发生(A减钱,B加钱),才能算做逻辑上的正确,这些事情形成了一个逻辑处理单元。
事务的宏观特性(程序员眼中的事务)
事务的微观特性(DBMS看到的事务)
事务的特性
下面再次回顾前面提到的不一致性问题。
这些事务,宏观上是独立完整的,然而到了微观层面(DBMS)就变成了微观交错执行了。并发控制主要是针对微观层面的。
后面我们会提到事务如何去解决这些问题。
【TODO:深入阐释】事务的特性: ACID
DBMS对事务的控制
- 【事务调度器】在确保事务一致性方面,发挥了重大的作用。(后面会进行详细的介绍)
- 【锁表】在协调事务过程中发挥着重要作用。DBMS深得数据库思想(仿佛一切都通过表来存储),锁也是存储数据库得表中的。
事务调度与可串行性
- 【事务调度】为了让我们方便理解,我们可以做出这样的假定,在事务调度的眼中,各个事务被打碎成一个个小的片段(比如,读、写、锁等),每个片段被标识了一些属性(比如属于哪个事务,次序,读写属性等)。然后事务调度其将会就这些片段安排出一个合理的次序。
- 【串行调度】串行调度,是将一个事务看作一个整体(不会被打散,不会被其它事务在执行过程中打断),一个事务执行完后,再去执行另一个事务。 --> 之所以提到串行调度,是因为该串行调度往往作为一个事务调度正确的参考模型,因为其足够简单且逻辑正确。
- 【并发或并行调度】串行调度虽然逻辑上正确,然而却是十分低效的。数据库要想高效执行,必须引入并发/并行,但引入并发后,就必须通过一些规则约束(后面会提到),来确保并发执行的结果是正确的。
并发调度的正确性
并发调度是高效的 。但与此同时,也引入了相应的复杂性。
并发调度的引入,意味着相当多的调度方案,哪一种是正确的呢?
示例:
- 从结果等价角度判断并发调度的正确性。
- 从形式角度,判断并发调度为可串行化调度,进而推导出结果的正确性。
一种简单的事务标记模型
假设事务中,只包含读和写。于是,一个事务,可通过如下模型进行刻画,即事务可以看作是读写组成的序列。
【关键定义】冲突:
规定了事务之间,事务内部,哪些是冲突的.
进而给出了冲突等价的定义. s1 通过的非冲突变换,最后使得其变换成s2.
–> 称s1 和 s2 是冲突等价的.【概念构建】在冲突等价概念下,又提出了串行化的概念.如果事务执行序列的交换次序后,最后等价于的某个串行化的执行的结果,那么称原来的并发执行为可串行化.
- 注意冲突的定义 & 冲突的规则。
【关键概念】冲突可串行性:
- 冲突是禁止交换的。非冲突是可以交换的。(按照上面的规则,算法是不难实现的)
概念区分: