为了获得最大的性能,通常数据库都有并发机制,不过带来的问题就是数据访问的冲突。为了解决这个问题,大多数数据库用的方法就是数据的锁定。sql
数据的锁定分为两种方法,第一种叫作悲观锁,第二种叫作乐观锁。什么叫悲观锁呢,悲观锁顾名思义,就是对数据的冲突采起一种悲观的态度,也就是说假设数据确定会冲突,因此在数据开始读取的时候就把数据锁定住。而乐观锁就是认为数据通常状况下不会形成冲突,因此在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,若是发现冲突了,则让用户返回错误的信息,让用户决定如何去作。数据库
先从悲观锁开始说。在SqlServer等其他不少数据库中,数据的锁定一般采用页级锁的方式,也就是说对一张表内的数据是一种串行化的更新插入机制,在任什么时候间同一张表只会插1条数据,别的想插入的数据要等到这一条数据插完之后才能依次插入。带来的后果就是性能的下降,在多用户并发访问的时候,当对一张表进行频繁操做时,会发现响应效率很低,数据库常常处于一种假死状态。而Oracle用的是行级锁,只是对想锁定的数据才进行锁定,其他的数据不相干,因此在对Oracle表中并发插数据的时候,基本上不会有任何影响。session
注:对于悲观锁是针对并发的可能性比较大,而通常在咱们的应用中用乐观锁足以。并发
Oracle的悲观锁须要利用一条现有的链接,分红两种方式,从SQL语句的区别来看,就是一种是 for update,一种是 for update nowait 的形式。好比咱们看一个例子。首先创建测试用的数据库表。性能
CREATE TABLE TEST(ID,NAME,LOCATION,VALUE,CONSTRAINT test_pk PRIMARY KEY(ID))AS SELECT deptno, dname, loc, 1 FROM scott.dept;
这里咱们利用了Oracle的Sample的scott用户的表,把数据copy到咱们的test表中。首先咱们看一下for update锁定方式。首先咱们执行以下的select for update语句。测试
select * from test where id = 10 for update;
经过这条检索语句锁定之后,再开另一个sql*plus窗口进行操做,再把上面这条sql语句执行一便,你会发现sqlplus好像死在那里了,好像检索不到数据的样子,可是也不返回任何结果,就属于卡在那里的感受。这个时候是什么缘由呢,就是一开始的第一个Session中的select for update语句把数据锁定住了。因为这里锁定的机制是wait的状态(只要不表示nowait那就是wait),因此第二个Session(也就是卡住的那个sql*plus)中当前这个检索就处于等待状态。当第一个session最后commit或者rollback以后,第二个session中的检索结果就是自动跳出来,而且也把数据锁定住。不过若是你第二个session中你的检索语句以下所示。spa
select * from test where id = 10;
也就是没有for update这种锁定数据的语句的话,就不会形成阻塞了。另一种状况,就是当数据库数据被锁定的时候,也就是执行刚才for update那条sql之后,咱们在另一个session中执行for update nowait后又是什么样呢。好比以下的sql语句。 因为这条语句中是制定采用nowait方式来进行检索,因此当发现数据被别的session锁定中的时候,就会迅速返回ORA-00054错误,内容是资源正忙, 但指定以 NOWAIT 方式获取资源。因此在程序中咱们能够采用nowait方式迅速判断当前数据是否被锁定中,若是锁定中的话,就要采起相应的业务措施进行处理。.net
select * from test where id = 10 for update nowait;
那这里另一个问题,就是当咱们锁定住数据的时候,咱们对数据进行更新和删除的话会是什么样呢。好比一样,咱们让第一个Session锁定住id=10的那条数据,咱们在第二个session中执行以下语句。code
update test set value=2 where id = 10;
这个时候咱们发现update语句就好像select for update语句同样也停住卡在这里,当你第一个session放开锁定之后update才能正常运行。当你update运行后,数据又被你update语句锁定住了,这个时候只要你update后尚未commit,别的session照样不能对数据进行锁定更新等等。blog
总之,Oracle中的悲观锁就是利用Oracle的Connection对数据进行锁定。在Oracle中,用这种行级锁带来的性能损失是很小的,只是要注意程序逻辑,不要给你一不当心搞成死锁了就好。并且因为数据的及时锁定,在数据提交时候就不呼出现冲突,能够省去不少恼人的数据冲突处理。缺点就是你必需要始终有一条数据库链接,就是说在整个锁定到最后放开锁的过程当中,你的数据库联接要始终保持住。与悲观锁相对的,咱们有了乐观锁。乐观锁一开始也说了,就是一开始假设不会形成数据冲突,在最后提交的时候再进行数据冲突检测。在乐观锁中,咱们有3种经常使用的作法来实现。