暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

oceanBase 如何保证事务的隔离性

手机用户7421 2024-09-13
186

数据库系统不能只服务一个用户,需要允许多个用户同时操作数据,即并发。所以需要保证多个并发事务的隔离,这里涉及到并发控制技术,常见的并发控制方法有基于锁的并发控制(Lock based Concurrency Controll)和多版本并发控制(Multiple version Concurrency Controll)



基于锁的并发控制

数据库系统对用户在事务过程中操作的每一行数据都加锁,读操作加读锁,写操作加写锁。读写阻塞,写写阻塞。如果两个不同的事务试图修改同一行数据,事务1先加上写锁正常执行,事务2就只能阻塞等待,当事务1执行结束释放写锁后,事务2再继续执行。

以转账操作为例,A账户有100元,B账户有200元,如果事务1执行从A账户转10元到B账户,那么在事务1执行过程中,A B两行账户数据都会被加上写锁。如果事务2执行另一次转账操作,从A账户转50元到B账户,那么给A加写锁时失败,事务2会一直等待直到加写锁成功为止。

如果在事务1与事务2的执行过程中,又来一个事务3想要查询A B两个账户的余额总和,那么需要读取A、B两行,读之前要先加读锁,但是在事务1和事务2操作时,读锁加不成功,那么事务3就需要等待事务1和事务2都结束了才能执行。


多版本的并发控制

在上面例子中,一个读取A、B两账户余额总和的操作,无论事务1和事务2是否执行完成,其结果都是确定的(300元)。但基于锁的并发控制,读写是阻塞的,极大的降低了数据库的并发性能,所以出现了MVCC的方法来做并发控制。对于数据库的数据,每次修改都保留历史版本,这样读操作可以直接在历史版本上执行,不会被写操作阻塞。

在MVCC方法下,每一个事务都会有一个提交版本,继续上面事务三的例子。假设数据的初始版本是98,假定事务1是的版本号100,事务2是101。那么修改都完成后,数据库中的数据状态如下:

图片

每次数据修改的记录都会被串联起来。另有一个全局变量Global Committed Version(GCV) 标示全局最后提交的版本号。在事务1执行之前GCV是98,事务1提交之后GCV变成100,事务二提交之后GCV变成101。所以,当事务3开始执行时,先获取GCV,然后根据这个版本号去读相应的数据。

MVCC的修改操作依然会依赖上面提到的锁机制,所以写操作之间的冲突依然需要等待。但是MVCC最大的优势就是读操作与写操作完全隔离开,互相不影响,对于数据库的性能和并发能力提升非常有益。

OceanBase使用的方案

使用MVCC方案时GCV的修改需要依次递增,如果GCV被修改成了101,表示101及之前的所有事务都提交了。OceanBase使用了分布式事务后,这个保证变得困难,例如,版本号为100的事务可能是分布式事务,101可能是单机事务,分布式事务的提交过程要显著长于单机事务。结果,版本号101的事务先完成,GCV就被修改成了101。但是此时版本号为100事务还在提交过程中,并不能被读取。

所以,OceanBase采用了MVCC和Lock-based结合的方式,读取操作先获取GCV,然后按照这个版本号读取每一行数据。如果这行数据上没有修改,或者有修改但是修改的版本号会大于GCV,那么这行数据可以直接按照版本号读取。如果这行数据上有一个正在提交中事务,并且版本号有可能小于读取使用的版本号,那么读取操作就需要等待这个事务结束,就好像Lock-based方案中读锁等待写锁一样。但是,这个发生的概率极低,所以整体的性能还是像MVCC一样好。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论