在多用户下,并发与一致性显得十分重要,现在通过实例来加以分析。并发操作,我们知道可能造成数据的不一致性,怎么来解决呢?很多地方都会遇到这种情况,可以采取加锁的方式来避免。从模式上来分,可以分为共享锁和排它锁,从字面上可以很好的理解它们的意思;从粒度上讲,可以分为表级锁和行级锁,表级锁就是锁定整个表(如比不同删除表或者修改表的结构);行级锁就是作用在某些行上,如果修改了某一行,就在这个行上加行级排它锁,其它的就不能访问这个行了。当然具体有锁的不同模式,如行级排它锁等,我想没有必要去讲得这么细,现在只需要知道有这些基本的概念在这里就行了。
提到并发与一致性,又不得提到事务,事务有不同的隔离级别,对应解决脏读(读到了别人没有提交的事务)、不可重复读(两次读操作得到的结果不同)、幻读(有人添加了数据)情况。每个事务都有一个事务ID,事务存在数据块的事务槽中,它有不同的状态。
讲到了事务,不得不说undo和redo,undo是保存数据修改之前的信息;而redo是重复这个操作。具体它们的结构还得单独去深入研究,在这里仅仅给出它们的基本功能。
假设我们设定的隔离级别为Read Committed.现在来分析两个会话对一张表的操作,看看具体的结果是怎样的?
有一张表:Person
Name Age
aaa 20
bbb 30
一个会话A做:delete from Person where Name like 'aaa';(现在没有commit)
此时在aaa这一行加上了行级排它锁,但是没有commit,此时生成了redo 和 undo的信息。
另一个会话B做:select * from Person;
它的结果是:Name Age
aaa 20
bbb 30
B在查询时,发现这一行有行级排它锁,再看看它的事务提交没,如果没有提交,就从undo中找到它被修改之前的值,所以返回上面的结果信息。
总结一下流程:
1)找到对应数据块的信息,发现这一行被锁定,再找到对应的事务ID;
2)发现事务是没有提交的,根据这个事务ID到undo块中去找之前的信息(undo中也存有事务的ID信息);
3)将没有标记锁定的行读出来和undo修改之前的信息读出来。
现在又有一个问题来了,不是说只能读到已提交的数据吗?ok,我们再来看一个问题。
会话A:读一个表的数据,假设读的过程很长;
会话B:在会话A中,删除了该表的某一行,commit了;
现在会话A会发现这个删除的行吗?即是少读了一行。
这里又不得不说一个概念就是SCN,这个是只会增加不会减少的数字标志。读的过程相当于一个快照,假设这个时刻有1000行,而在读的过程中删除了一行,其实A是不会发现的,这是因为在上一刻的时间点(快照)就是1000行,所以不会读到999行。这是怎么来实现的呢。就是依靠这个SCN。
SCN按照时间来生产的,在某个时刻,它的编号是100,如果过一会儿,又有事务在数据块中修改数据,此时的SCN变成了102,那么SCN为100的事务发现有比自己大的SCN存在,就说明有人修改了数据,所以必需从undo中找出之前的数据,所以才会返回1000行数据。
今天只是从宏观上说说oracle 数据的并行和一致性,里面有很多细的东西深入我们去学习,后面我也会写一系列的文章来分享我的学习体会。
提到并发与一致性,又不得提到事务,事务有不同的隔离级别,对应解决脏读(读到了别人没有提交的事务)、不可重复读(两次读操作得到的结果不同)、幻读(有人添加了数据)情况。每个事务都有一个事务ID,事务存在数据块的事务槽中,它有不同的状态。
讲到了事务,不得不说undo和redo,undo是保存数据修改之前的信息;而redo是重复这个操作。具体它们的结构还得单独去深入研究,在这里仅仅给出它们的基本功能。
假设我们设定的隔离级别为Read Committed.现在来分析两个会话对一张表的操作,看看具体的结果是怎样的?
有一张表:Person
Name Age
aaa 20
bbb 30
一个会话A做:delete from Person where Name like 'aaa';(现在没有commit)
此时在aaa这一行加上了行级排它锁,但是没有commit,此时生成了redo 和 undo的信息。
另一个会话B做:select * from Person;
它的结果是:Name Age
aaa 20
bbb 30
B在查询时,发现这一行有行级排它锁,再看看它的事务提交没,如果没有提交,就从undo中找到它被修改之前的值,所以返回上面的结果信息。
总结一下流程:
1)找到对应数据块的信息,发现这一行被锁定,再找到对应的事务ID;
2)发现事务是没有提交的,根据这个事务ID到undo块中去找之前的信息(undo中也存有事务的ID信息);
3)将没有标记锁定的行读出来和undo修改之前的信息读出来。
现在又有一个问题来了,不是说只能读到已提交的数据吗?ok,我们再来看一个问题。
会话A:读一个表的数据,假设读的过程很长;
会话B:在会话A中,删除了该表的某一行,commit了;
现在会话A会发现这个删除的行吗?即是少读了一行。
这里又不得不说一个概念就是SCN,这个是只会增加不会减少的数字标志。读的过程相当于一个快照,假设这个时刻有1000行,而在读的过程中删除了一行,其实A是不会发现的,这是因为在上一刻的时间点(快照)就是1000行,所以不会读到999行。这是怎么来实现的呢。就是依靠这个SCN。
SCN按照时间来生产的,在某个时刻,它的编号是100,如果过一会儿,又有事务在数据块中修改数据,此时的SCN变成了102,那么SCN为100的事务发现有比自己大的SCN存在,就说明有人修改了数据,所以必需从undo中找出之前的数据,所以才会返回1000行数据。
今天只是从宏观上说说oracle 数据的并行和一致性,里面有很多细的东西深入我们去学习,后面我也会写一系列的文章来分享我的学习体会。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/30024515/viewspace-1434671/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/30024515/viewspace-1434671/