数据库并发控制的三个问题

现在主流的数据库管理系统中,都支持多个事务同时执行,这样提高了数据库管理系统的运行效率。试想如果只允许一个事务运行,而这个事务又需要很长的时间,那么其他的用户必须一直等待该事务结束,效率何其低下。执行不同的事务虽然可以提高性能,但是有可能会破坏数据的完整性,所以我们必须在性能和数据完整性之间进行权衡。那么什么是并发控制呢?并发控制是数据库管理系统协调多个运行事务的行为。首先了解一下,并发控制中经常遇到的三个问题。

1.脏读

我们通过一个products表来解释一下什么是脏读,该products表有一列quantity(数量),现在的值为20。假如现在有两个事务T1和T2,它们都是要更新quantity列,T1将该列值加100,T2将此列减10,但是T1执行失败进行了回滚。我们很容易计算出正确的结果20-10=10,但是如果事务按照以下方式运行,能够得出什么结果?
时间   事务   步骤                             存储值
1      T1     读出quantity的值                20
2      T1      quantity=20+100             120
3      T1      写入quantity值                  120
4      T2      读出quantity(T1未提交)     120
5      T2      quantity=120-10             110
6      T1      回滚(rollback)                  20
7      T2      写入quantity值                 110
以上得出了110的结果,显然是不正确的,问题就在于T2读取到了T1没有提交的数据,我们把这种情况就称之为脏读。

2.不可重复读

还是事务T1和T2,它们都是要更新quantity列,T1将该列值加100,T2将此列减10,而且两个事务都成功。我们很容易计算出正确的结果20+100-10=110,但是如果事务按照以下方式运行,能够得出什么结果?
时间   事务   步骤                             存储值
1      T1     读出quantity的值                20
2      T2     读出quantity的值               20
3      T1     quantity=20+100                  120
4      T2     quantity=20-10                  10
5      T1     写入quantity值(更新丢失)          110
6      T2     写入quantity值                  10
得出了10的结果,仍然是不正确的。问题就在于T2的值覆盖了T1的值,我们把这种情况称之为不可重复读。

3.幻觉读

例如T1对一个表中的所有行修改,同时T2向该表中插入一行记录。这时在T1中就会发生还有没有被修改的数据行,就好象发生了幻觉一样。
    
Oracle提供了三种隔离级别,分别是Read Committed Serializable和Read Only。Read Committed是Oracle的默认隔离级别,可以看出这种隔离级别消除了脏读,但是避免不了不可重复读和幻觉读的发生,不过一般的应用还是可以使用该隔离级别的。Serializable这种隔离级别可以消除以上三个问题,但是效率会降低很多。Read Only隔离级别不是SQL92标准中定义的,它不允许事务进行更新操作,这种隔离级别也可以消除脏读。
Oracle中在事务开始之前可以通过以下方式设置隔离级别:
set transation isolation level read committed;
set transation isolation level serialezable;
set transation isolation level read only;

也可以在单独的会话中设置隔离级别:
alter session set isolation_level read committed;
alter session set isolation_level serialezable;
alter session set isolation_level read only;

通过刚才的介绍,我们知道了可以设置隔离级别来降低或者消除数据的不完整性,那数据库管理系统是怎么做到这一点的呢?答案是,采用锁。锁可以保护数据,当一个事务修改数据时,锁会将该数据锁定,防止这些数据在同一时刻被其它事务修改。
大多数情况下,我们可以不必自己管理锁,Oracle会自动创建并管理,但是了解锁是如何工作的,对我们来说也是非常有必要的。下列这些情况Oracle会创建锁:
当我们运行了create truncate alter语句时,Oracle会创建锁,称之为DDL锁。
当我们运行了insert update delete语句,Oracle会创建锁,称之为DML锁。
还有一种是内部锁,由Oracle在内部使用,比如管理数据文件。在这里我们不做介绍。
从级别上讲,锁还可以分为数据库级别锁、表级别锁、行级别锁和列级别锁(Oracle不支持)。
1、数据库级别锁:它会锁定数据库以禁止任何新会话和新事务。锁定数据库的最主要目的是在没有用户干扰的情况下完成维护。在Oracle中使用以下语句锁定数据库为限制模式:
alter system enable restricted session;
通过下列语句取消数据库限制模式:
alter system disable restricted session;
以下语句将锁定数据库为只读模式:
startup mount;
alter database open read only;
2、表级别锁:它会锁定整张表,以防止其它事务对表结构进行修改。比如当我们运行一个insert语句,如果表没有没锁定,其它的事务修改了一列(将列名修改),这时我们运行update语句就会出错,所以当我们运行DML语句时,Oracle会自动将表锁定,DML语句执行完,会释放表级别锁。我们也可以通过lock语句锁定表。
3、行级别锁:当我们运行DML语句时,当前行上就会有行级别锁,防止其它事务对该行进行修改。
手工释放锁:alter system kill session 'sid,serial#';

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值