OceanBase如何保证事务的隔离性
数据库系统不能只服务一个用户,需要允许多个用户同时操作数据,即并发。所以需要保证多个并发事务的隔离,这里涉及到并发控制技术,常见的并发控制方法有基于锁的并发控制(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最大的优势就是读操作与写操作完全隔离开,互相不影响,对于数据库的性能和并发能力提升非常有益。
原文链接:https://blog.csdn.net/fuzhongmin05/article/details/118196626




