冬雨财经 发表于 2025-1-9 06:18:04

数据库系统概论:数据库的并发控制

数据库并发控制

数据库并发控制是数据库管理系统(DBMS)中的一种紧张策略,用于确保在多个用户或事务同时访问数据库时,数据的同等性和隔离性得到维护。
主要目的

数据库并发控制是指管理多个事务同时访问同一数据库时的数据同等性和完整性,以防止数据辩论和差别等。其主要目的包括:

[*]制止更新丢失:确保当多个事务同时更新同一条纪录时,全部的更新都能得到保存,而不是被其他事务的操作覆盖。
[*]制止脏读:防止一个事务读取了另一个事务未提交的更新,这大概导致读取到错误的数据。
[*]制止不可重复读:确保在同一事务中,多次读取同一数据的效果是同等的,防止在两次读取之间有其他事务对数据进行更新。
[*]制止幻读:确保在一个事务实行过程中,同一查询在事务开始和竣事时看到的行数是同等的,防止在事务实行过程中有其他事务插入或删除纪录。
办理方案

数据库并发控制主要接纳以下几种:

[*]锁机制:

[*]共享锁(S锁):允很多个事务同时读取同一数据,但不允许修改。
[*]排他锁(X锁):禁止其他事务读取或写入锁定的数据,确保写操作的独占性。
[*]锁的粒度:包括行级锁、表级锁和页级锁,差别的锁粒度对系统性能和数据同等性有差别的影响。
[*]两阶段锁协议(2PL):事务分为加锁阶段和解锁阶段,加锁阶段可以不断申请锁但不能开释锁,解锁阶段可以开释锁但不能再申请锁。

[*]时间戳技能:

[*]为每个事务分配一个唯一的时间戳,根据时间戳的次序来控制事务的并发实行,制止事务之间的辩论。
[*]时间戳排序方法包括基本时间戳排序和多版本时间戳排序。

[*]多版本并发控制(MVCC):

[*]通过为每个数据对象维护多个版本,允许事务在不互相壅闭的情况下并发实行。
[*]包括快照隔离和可序列化隔离,快照隔离在事务开始时创建数据的快照,事务在实行期间读取快照数据;可序列化隔离则通过维护数据对象的多个版本,实现事务的序列化实行。

[*]乐观并发控制(OCC):

[*]假设数据辩论很少发生,事务在实行期间不进行锁定,提交时再检查辩论。
[*]如果发现辩论,则回滚事务并重新实行。

隔离级别

隔离级别(Isolation Level)是指多个事务并发实行时,为保证数据的同等性和正确性所接纳的控制方案。差别的隔离级别决定了数据库系统如何以及在多大水平上保证事务之间的隔离和并发实行。
隔离级别决定了事务在并发情况中访问和修改数据时的可见性和同等性。数据库的隔离级别主要用来处理并发控制问题,制止脏读、不可重复读、幻读等征象。
数据库系统概论:事务与并发同等性问题
读未提交

读未提交(Read Uncommitted) 是数据库事务隔离级别中的最低级别。在读未提交的隔离级别下,一个事务可以读取另一个事务尚未提交的修改。
在读未提交级别下,事务可以读取到其他事务所做的临时修改,即使这些修改终极大概会被回滚或不提交。
读未提交的隔离级别固然可以提供最高的并发性和读取性能,但同时也带来了一些严重的问题,包括:


[*]脏读(Dirty Read)
[*]不可重复读(Non-Repeatable Read)
[*]幻读(Phantom Read)
由于读未提交级别的问题比力严重且不符合数据的同等性要求,因此在实际应用中较少使用。
读已提交

读已提交(Read Committed):在读已提交的隔离级别下,一个事务只能读取到已经提交的其他事务所做的修改,一个事务所做的修改在提交之前对其它事务是不可见的。
读已提交级别办理了读未提交级别的脏读问题,确保了事务之间的数据隔离性和同等性。在这个级别下,每次读取都只能读取到已提交的数据,从而制止了读取到差别等或无效数据的情况。
但是,读已提交级别仍旧大概导致不可重复读(Non-Repeatable Read)和幻读(Phantom Read)的问题
读已提交级别下的并发读取仍旧存在竞争条件和问题。多个事务可以同时读取同一数据,而且其他事务可以在读取操作之间修改该数据。因此,读已提交级别大概导致一些差别等的效果,但可以制止脏读。
如果应用程序需要更高的数据同等性,可以思量使用更严格的隔离级别,如可重复读或可串行化。但请注意,更严格的隔离级别大概会带来更多的锁争用和性能开销。需要根据具体应用场景和需求进行衡量和选择。
可重复读

可重复读(Repeatable Read):在可重复读的隔离级别下,事务在实行过程中看到的数据集是同等的,即便其他事务对数据进行了修改,事务也不会读取到这些修改。
在可重复读级别下,一个事务在开始时会创建一个同等性视图,该视图包含事务开始时数据库中的全部数据。事务读取的数据都是基于该同等性视图,不受其他并发事务对数据的修改影响。即使其他事务对数据进行了插入、更新或删除操作,事务读取的数据仍旧保持同等。
可重复读级别办理了读已提交级别的不可重复读问题,确保了在同一个事务中多次读取同一条纪录时,得到的效果是同等的。但是,可重复读级别仍旧大概导致幻读(Phantom Read)的问题
可串行化

可串行性是并发事务正确调度的准则,即一个给定的并发调度,当且仅当它是可串行化的,才认为是正确调度
串行化调度

可串行化调度(Serializable Schedule),多个事务并发实行的情况下,系统能够保证各个事务的实行效果和以某种次序串行实行的效果同等的调度方式。
简而言之,就是系统对并发实行的多个事务进行调度时,当且仅当其效果与按某一次序串行地实行这些事务时的效果相同。在可串行化调度下,多个事务固然并发实行,但是它们的操作次序看上去像是在一个串行的时间轴上运行。
为了实现可串行化调度,数据库系统应该满意 ACID(原子性、同等性、隔离性、持久性)的特性,并通过各种 锁机制、MVCC(多版本并发控制)等技能来办理并发操作的问题,确保每个事务操作实行的正确次序。具体来说,可串行化调度需要满意以下两个条件:

[*] 等价原则:系统实行的效果和全部大概的串行实行效果相等。
[*] 视图可重构性:系统的实行效果不受事务提交的次序影响。
可串行化 Serializable

可串行化(Serializable)是数据库事务隔离级别中的最高级别,也是最严格的隔离级别。在可串行化的隔离级别下,事务串行实行,保证了最高级别的数据隔离性和同等性。
在可串行化级别下,一个事务在实行期间会对所涉及的数据进行锁定,防止其他事务对这些数据进行并发的读取、写入、插入或删除操作。这意味着其他事务无法与正在实行的事务并发地操作相同的数据。
可串行化级别办理了读已提交和可重复读级别中的脏读、不可重复读和幻读问题。由于事务串行实行,一个事务只能看到其他事务已提交的数据,不会读取到其他事务未提交的数据。同时,其他事务也无法修改已被锁定的数据,从而保证了数据的同等性。
尽管可串行化级别提供了最高的隔离性,但也大概带来较高的性能开销。由于并发实行被限制了,事务需要等待其他事务开释锁才能继承实行,大概导致性能降落。
通常情况下,只有在特殊的需求下才会选择可串行化级别,比方对数据同等性要求非常高、并发辩论风险较大的场景。
大多数应用场景下,Repeatable Read 或 Read Commited 级别已经能够满意数据隔离和同等性的需求。在选择隔离级别时,需要仔细评估应用的需求、并发访问模式和性能要求。
辩论可串行化

辩论操作:是指差别事务对同一个数据的读写操作和写写操作。除此之外,其他操作均为不辩论操作


[*] 事务                                                          T                                  i                                                 T_i                        Ti​ 读数据                                              X                                    X                        X ,事务                                                          T                                  j                                                 T_j                        Tj​ 写数据                                              X                                    X                        X
[*] 事务                                                          T                                  i                                                 T_i                        Ti​ 写数据                                              X                                    X                        X ,事务                                                          T                                  j                                                 T_j                        Tj​ 写数据                                              X                                    X                        X
[*] 差别事务的辩论操作不可互换
[*] 同一事务内部的两个操作不可互换
[*] 差别事务,同一数据的读读操作可以互换
[*] 差别事务,差别数据,无论读写均可互换
可串行化调度的充分条件是辩论可串行化
辩论可串行化:一个调度                                    S                         C                              SC                  SC 在保证辩论操作的次序不变的情况下,通过互换两个事务不辩论操作的次序得到另一个调度                                    S                                 C                            ‘                                       SC^`                  SC‘ 。如果                                    S                                 C                            ‘                                       SC^`                  SC‘ 是串行的,则称调度                                    S                         C                              SC                  SC 为辩论可串行化的调度。若一个调度是辩论可串行化的,那么它肯定是可串行化的调度
多版本并发控制

多版本并发控制(Multi-Version Concurrency Control,MVCC)是一种用于实现数据库并发控制的技能。它通过在数据库中维护多个数据版原来达到事务的隔离,并允许事务并发实行而不会相互影响。
MVCC 也是 MySQL 的 InnoDB 存储引擎实现隔离级别的一种具体方式,用于实现 Read Commited 和 Repeatable Read 这两种隔离级别。而 Read Uncommited 总是读取最新的数据行,无需使用 MVCC。Serializable 隔离级别需要对全部读取的行都加锁,单纯使用 MVCC 无法实现。
MVCC 的基本思想是,在每次数据修改操作(如插入、更新、删除)时,将新的数据版本存储在数据库中,而不是立即覆盖原有的数据版本。每个事务在开始时创建一个时间戳(如事务开始的时间),该时间戳被用于标识该事务所能看到的数据版本。
当一个事务读取数据时,它只能看到那些在其开始时间之前已经提交的数据版本。这意味着每个事务都能看到一个同等性的数据视图,即使其他事务正在并发地修改或删除数据。事务读取的数据版本不受其他事务未提交修改的影响,从而办理了 可重复读 级别下的“不可重复读”和“幻读”的问题。
MVCC 通过在每个数据版本上维护一些元信息(如版本号、创建时间戳、烧毁时间戳等)来实现事务隔离。
数据库系统根据事务的时间戳和数据版本的元信息来决定事务能否读取或修改数据,而且在并发操作中进行辩论检测和办理。
MVCC 的好处是能够提供较高的并发性能,由于读操作不会互斥地锁定数据,多个事务可以并发地读取相同的数据。然而,它也需要额外的存储空间来保存多个数据版本,并在查询时进行版本的选择和判断。
MVCC 是很多现代数据库系统的焦点技能,如 PostgreSQL、MySQL 的 InnoDB 引擎等,它们使用 MVCC 来实现差别的隔离级别,并提供高效的并发控制和数据同等性。
版本号

版本号是一种元数据,用于标识数据的差别版本。
在 MVCC 中,每个数据版本都会分配一个唯一的版本号,事务读取数据时使用该版本号来决定读取哪个版本的数据。版本号通常作为数据的隐蔽列存储在数据库中,对应于每个数据行都会有一个版本号。
系统版本号

在数据库中,系统版本号是指标识一个数据库管理系统发布的版本的编号或标识符。
通常情况下,数据库系统版本号由数字、字母等组成,遵循肯定的命名规则或约定。差别的数据库管理系统各自具有差别的版本号格式和命名规则。每开始一个新的事务,系统版本号就会主动递增。
事务版本号

事务版本号是指在事务处理过程中,为了实现并发控制和隔离性,为每个事务标识的唯一编号或标识符,为事务开始时的系统版本号。
在并发实行的事务中,事务版本号用于确保事务之间的隔离和同等性,制止读取到其他事务未提交的数据或读取到已被其他事务修改的数据。
事务版本号可以通过数据库管理系统或事务管理机制来天生和管理,以确保事务的序列化次序和隔离性。
快照

快照是一个时间点的数据库图像(副本),用于事务实行过程中获取同等性的数据视图。
在 MVCC 中,每个事务都会建立一个快照,该快照会纪录事务开始时间点的数据库状态(全部表的内容和状态),包括当前未提交的事务产生的数据版本。在事务实行过程中,事务只能看到快照中纪录的最新数据版本。
快照通常用于数据备份、故障规复、数据历史查询和同等性读取等目的。通过创建数据库的快照,可以将数据库还原到某个特定时间点的状态,或者用于天生数据报表等操作。
Undo 日志

在数据库中,Undo日志(Undo Log)是一种纪录事务操作的数据结构。它纪录了在事务操作中所做的修改的逆操作,在回滚、并发控制以及规复系统中起到紧张作用。
当一个事务修改了数据库中的数据时,Undo日志 会纪录这个修改前的数据,即旧值。如果事务需要回滚,或者系统需要将数据回滚到某个特定的时间点,就可以使用这些旧值将数据回滚到原始状态。另外,Undo日志也可以用于并发控制,防止事务之间的修改相互干扰。
在数据库中,Undo日志 通常是通过两种方式实现:

[*] 在更新数据前将旧数据写入 Undo日志,然后将新值写入磁盘,以确保数据更新的原子性。如果事务需要回滚,就可以使用 Undo日志 中的旧值来还原数据。
[*] 通过 MVCC 技能,在每个事务完成之后,将其修改的数据和旧值保存在Undo日志中,以便其他事务可以读取此中的旧值。该日志通过回滚指针把一个数据行(Record)的全部快照连接起来
https://i-blog.csdnimg.cn/direct/9df7d28b621d4abf9c7a88996a4a6a8b.png
数据隐蔽列

数据隐蔽列是指在数据库表中定义的列,这些列不会直接对外暴露,寻常用户无法直接访问或操作它们。隐蔽列通常用于存储一些辅助信息或元数据,这些信息对于数据库系统内部的操作和控制非常紧张,但对于寻常用户来说是不可见的。
隐蔽列在多种数据管理场景中都有广泛的应用:

[*] 版本号列:在实现多版本并发控制(MVCC)的数据库中,每个数据版本会关联一个版本号,这个版本号通常作为隐蔽列存储在表中。它用于标识数据的差别版本,以实现事务隔离和读取同等性。
[*] 创建时间戳和更新时间戳列:这些隐蔽列用于纪录数据的创建时间和上次更新时间。它们可以用于数据审计、版本追踪和性能优化等目的。
[*] 删除标记列:在逻辑删除的场景中,可以添加一个隐蔽的逻辑删除标记列来表示数据是否被删除。这样可以制止物理删除,而是通过更新隐蔽列的值来实现逻辑删除的功能。
如果该快照的删除版本号大于当前事务版本号表示该快照有效,否则表示该快照已经被删除了。
[*] 数据行版本列:在某些情况下,为了实现数据的同步和辩论检测,可以添加一个隐蔽的数据行版本列。
指示创建一个数据行的快照时的系统版本号,该列存储一个递增的整数值,每当数据行发生变化时,版本号就会增长,从而确保其他操作不会同时修改相同的数据行。
隐蔽列可以通过数据库管理工具或查询语言来访问和操作,但寻常用户在进行数据操作时通常无需关注或直接使用它们,由于它们主要是为了提供一些内部的管理和控制功能。隐蔽列的存在提供了一种有效的方式来扩展数据库模式,加强数据的管理和控制能力。
在 Repeatable Read 级别下实现 MVCC

当开始新一个事务时,该事务的版本号肯定大于当前全部数据行快照的创建版本号

[*] SELECT:多个事务必须读取到同一个数据行的快照,而且这个快照是隔断现在最近的一个有效快照。
但如果有一个事务正在修改该数据行,那么它可以读取事务本身所做的修改,而不用和其它事务的读取效果同等。
把没有对一个数据行做修改的事务称为 T,T 所要读取的数据行快照的创建版本号必须小于 T 的版本号,由于如果大于或者等于 T 的版本号,那么表示该数据行快照是其它事务的最新修改,因此不能去读取它。
除此之外,T 所要读取的数据行快照的删除版本号必须大于 T 的版本号,由于如果小于等于 T 的版本号,那么表示该数据行快照是已经被删除的,不应该去读取它。
[*] INSERT:将当前系统版本号作为数据行快照的创建版本号
[*] DELETE:将当前系统版本号作为数据行快照的删除版本号
[*] UPDATE:将当前系统版本号作为更新前的数据行快照的删除版本号,并将当前系统版本号作为更新后的数据行快照的创建版本号。可以明白为先实行 DELETE 后实行 INSERT。
快照读和当前读

在数据库系统中,快照读和当前读是读取数据的两种方式。
经常使用的快照读取包括数据库中的多版本并发控制(MVCC)和快照隔离级别(Snapshot Isolation Level)等。而当前读取则通常应用于不需要特殊隔离级别的事务中。
快照读

快照读(Snapshot Read)是指在一个事务中按照一个固定时间点的视角来读取数据,也就是读取的是该事务开始之前的数据快照,淘汰加锁带来的开销。
select * from table ...;
在进行快照读取时,不会读取其他正在进行修改的事务的数据。这种方式的读取不会壅闭其他事务,因此可以保证高并发性和数据的同等性。但是,由于读取的是先前的数据快照,所以大概读取到已经更新或删除的数据。
当前读

当前读(Current Read)是指在一个事务中按照当前时间点的视角来读取数据,也就是读取的是最新的数据,需要加锁。
select * from table where ? lock in share mode;
select * from table where ? for update;
insert;
update;
delete;
在进行当前读取时,如果发现另一个事务正在修改已被读取的数据,则会被壅闭,直到该事务完成或回滚。这种方式的读取确保了读取数据的正确性,但大概会对并发性能产生影响。
总结

数据库并发控制是确保数据同等性和隔离性的关键技能。通过公道的封锁策略、并发调度协议以及得当的隔离级别,可以有效地办理并发带来的问题。在实际应用中,应根据具体需求选择符合的并发控制策略,以平衡并发度和数据同等性。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 数据库系统概论:数据库的并发控制