数据库MVCC,提高并发性能的关键技术 (数据库 mvcc)

随着互联网的飞速发展,数据库作为存储数据的基础设施,对于保障互联网业务的可靠性和稳定性起到了至关重要的作用。在互联网业务中,由于数据操作的并发性,数据库的并发性能成为了关键瓶颈。在众多的数据库技术中,MVCC技术成为了提高数据库并发性能的关键技术。

什么是MVCC技术?

MVCC全称为Multi-Version Concurrency Control,即多版本并发控制。MVCC技术是一种并发控制机制,它是为了解决数据库在高并发环境下数据一致性与性能的问题而提出的。MVCC是在保证事务一致性、隔离性的前提下提高数据库并发性能的重要技术。

MVCC技术的实现方式

MVCC技术的实现方式有两种,一种是基于版本链表,即在每个数据块中维护一个版本链表,每个版本链表节点包含一个版本号和对应的数据。另一种是基于快照隔离,即为每个事务创建一个数据库快照来进行事务处理。

基于版本链表的实现方式,采用了多版本存储数据,在读取数据时,将版本号更高的数据返回。同时,写入新数据时,基于CAS算法(Compare and Swap)实现原子性地更新。这样就能够实现数据的读取和写入的并发控制。在每个事务中,读取的数据版本号大于等于事务开始时的版本号,事务写入的数据版本号等于事务开始时的版本号。

基于快照隔离的实现方式,将每个事务隔离出来,每个事务处理时都有自己的数据库快照。快照中包含了事务开始时的所有数据。在事务处理过程中,不会对其他事务可见,其中数据的修改只有在事务提交时才会对其他事务可见。

MVCC技术的优点

MVCC技术的出现,主要是为了解决传统锁机制的死锁问题和性能问题。

在传统锁机制中,由于锁的粒度过大,因此容易发生死锁问题。同时,锁的开销也非常大,容易出现性能瓶颈。而MVCC技术实现了原子性,避免了死锁问题。同时,由于读取数据时只需要读取一个版本的数据,没有锁的粒度限制,因此将块粒度调小,从而提高并发性能。在读多写少的情况下,MVCC技术的性能更为优越。

在MVCC技术中,每个事务都有自己的快照,因此对其他事务的影响非常小,避免了传统锁机制中由于阻塞而造成的性能损失,提高了并发性能。同时,在MVCC技术中,对于读多写少的业务场景,可以采用基于快照隔离的方式实现,进一步提高了并发性能。

MVCC技术的应用

目前,MVCC技术已经广泛应用于各类数据库中。例如,Oracle数据库的默认隔离级别是Read Committed,它采用的就是MVCC技术。PostgreSQL数据库也采用了MVCC技术,并将其作为默认隔离级别。

同时,MVCC技术也被用于各种分布式系统中,如Hadoop、Spark等。这些分布式系统都需要对数据进行并发处理,因此也需要采用MVCC技术实现数据一致性和性能的平衡。

MVCC技术是一种非常重要的技术,为了解决传统锁机制在高并发场景下的性能和死锁问题而提出。该技术实现对读取数据和写入数据的并发控制,避免了锁的粒度问题和死锁问题,提高数据库的并发性能。同时,由于其应用范围广泛,因此成为了数据库和分布式系统中重要的技术,未来也将得到不断完善和发展。

相关问题拓展阅读:

Access数据库中如何避免脏数据

脏读dirtyreads:当事务读取还未被提交的数据时,就会发生这种事件。举例来说:Transaction1修改了一行数据,然后Transaction2在Transaction1还未提交修改操作之前读取了被修改的行。如果Transaction1回滚了修改操作,那么Transaction2读取的数据就可以看作是从未存在过的。

不可重复的读non-repeatablereads:当事务两次读取同一行数据,但每次得到的数据都不一样时,就会发生这种事件。举例来说:Transaction1读取一行数据,然后Transaction2修改或删除该行并提交修改操作。当Transaction1试图重新读取该行时,它就会得到不同的数据值(如果该行被更新)或发现该行不再存在(如果该行被删除)。

虚读phantomread:如果符合搜索条件的一行数据在后面的读取操作中出现,但该行数据却不属于最初的数据,就会发生这种事件。举例来说:Transaction1读取满足某种搜索条件的一些行,然后Transaction2插入了符合Transaction1的搜索条件的一个新行。如果Transaction1重新执行产生原来那些行的查询,就会得到不同的行。

MYSQL事务隔离级别的认识

:27

在hibernate中如果要连续不间断的保存多个实体的实例,那么在我们保存之一个的时候,其实在数据库里是不存在数据的,即使用Session.flush()也无济于事,这到底是怎么回事呢?让我很是疑惑…….

在查阅了相关的资料后,原来是数据库对于事务的隔离级别的限制问题,而我原来的MYSQL数据库正好是不支持我上述操作的隔离级别。

1、在MYSQL中查询事务隔离级别:

select@@tx_isolation;(tx其实就是transaction的缩写或者习惯缩写法)

我的结果是REPEATABLE-READ(即可重复读,稍后会引用专业结束文档)

2、修改MYSQL事务隔离界别:

settransactionisolationlevel目标隔离级别;

3、再次查询隔离级别进行检验是否已经成功修改。

这样在修改了隔离级别之后,在进行save()的时候,数据库中就会存在一些数据了,问题解决了。关于其他的数据库产品,思想都是一样的。

附加、官方的SQL事务隔离级别文档:

SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离野码级一般支持更高的并发处理,并拥有吵悉更低的系统开销。

ReadUncommitted(读取未提交内容)

在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少。读取未提交的数据,也被称之为脏读(DirtyRead)。

ReadCommitted(读取提交内容)

这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它满足了隔离的简单定义:一个事务只能看见已经提交事务所做的升脊乎改变。这种隔离级别也支持所谓的不可重复读(Read),因为同一事务的其他实例在该实例处理其间可能会有新的commit,所以同一select可能返回不同结果。

RepeatableRead(可重读)

这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。不过理论上,这会导致另一个棘手的问题:幻读(PhantomRead)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影”行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,ConcurrencyControl)机制解决了该问题。

(可串行化)

这是更高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争。

MySQL 事务的默认隔离级别是什么?可以解决幻读问题么?

我们设想一个场景,这个场景中我们需要插入多条相关联的数据到数据库,不幸的是,这个过程可能会遇到下面这些问题:

上面的任何一个问题都可能会导致数据的不一致性。为了保证数据的一致性,系统必须能够处理这些问题。事务就是我们抽象出来简化这些问题的首选机制。事务的概念起源于数据库,目前,已经成为一个比较广泛的概念。

何为事务?

一言蔽之,

事务是逻辑上的一组操作,要么都执行,要么都不执行。

事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账 1000 元,这个转账会涉及到两个关键操作,这两个操作必须都成功或者都失败。

事务会把这两个操作就可以看成逻辑上的一个整体,这个整体包含的操作要么都成功,要么都要失败。这样就不会出现小明余额减少而小红的余额却并没有增加的情况。

大多数情况下,我们在谈论事务的时候,如果没有特指

分布式事务

,往往指的就是

数据库事务

数据库事务在我们日常开发中接触的最多了。如果你的项目属于单体架构的话,你接触到的往往就是数据库事务了。

那数据库事务有什么作用呢?

简单来说,数据库事务可以保证多个对数据库的操作(也就是 SQL 语句)构成一个逻昌穗辑上的整体。构成这个逻辑上的整体的这些数据库操作遵循:

要么全部执行成功,要么全部不执行

另外,关系型数据库(例如: MySQL 、 SQL Server 、 Oracle 等)事务都有

ACID

特性:

ACID

这里要额外补充一点:

只有粗迅瞎保证了事务的持久性、原子性、隔离性之后,一致性才能得到保障。也就是说 A、I、D 是手段,C 是目的!

在典型的应用程序中,多个事务并发运行,经常会操作相同的数据来完成各自的任务(多个用户对同一数据进行操作)。并发虽然是必须的,但可能会导致以下的问题。

不可重复读和幻读区别

:不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改,幻读的重点在于新增或者删除比如多次查询同一条查询语句(DQL)时,记录发现记录增多或减少了。

SQL 标准定义了四个隔离级别:

隔离级别脏读不可重复读幻读 READ-UNCOMMITTED READ-COMMITTED REPEATABLE-READ SERIALIZABLE

MySQL 的隔离级别基于锁和 MVCC 机制共同实现的。

SERIALIZABLE 隔离级别,是通过锁来实现的。除了 SERIALIZABLE 隔离级别,其他的隔离级别都是基于 MVCC 实现。

不过, SERIALIZABLE 之外的其他隔离级别可能也需要用到锁机制,就比如 REPEATABLE-READ 在当前读情况下需要使用加锁读来保证不会出现幻读。

MySQL InnoDB 存储引擎的默认支持的隔离级别是

REPEATABLE-READ(可重读)

。我们可以通过 SELECT @@tx_isolation; 命令来查看,MySQL 8.0 该命令改为 SELECT @@transaction_isolation;

从上面对 SQL 标准定义了四个隔离级别的介绍可以看出,标准的 SQL 隔离级别定义里,REPEATABLE-READ(可重复读)是不可以防止幻读的。

但是!InnoDB 实现的 REPEATABLE-READ 隔离级别其实是可以解决幻读问题发生的,主要有下面两岩空种情况:

因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是

READ-COMMITTED

,但是你要知道的是 InnoDB 存储引擎默认使用

REPEATABLE-READ

并不会有任何性能损失。

InnoDB 存储引擎在分布式事务的情况下一般会用到 SERIALIZABLE 隔离级别。

数据库 mvcc的介绍就聊到这里吧,感谢你花时间阅读本站内容,更多关于数据库 mvcc,数据库MVCC,提高并发性能的关键技术,Access数据库中如何避免脏数据,MySQL 事务的默认隔离级别是什么?可以解决幻读问题么?的信息别忘了在本站进行查找喔。


数据运维技术 » 数据库MVCC,提高并发性能的关键技术 (数据库 mvcc)