一.数据库事务的属性(ACID)

1)原子性(Atomicity):组成一个事务的多个数据库操作是一个不可分割的原子单元,即要么全部执行,要么全部不执行。

2)一致性(Consistency):事务操作成功后,数据库所处的状态和它的业务规则是一致的,数据不会被破坏。(“一致性”是最终目标)

3)隔离性(Isolation):在并发数据操作时,不同的事务拥有各自的数据空间,它们的操作不会对对方产生干扰。(事务的隔离级别)

4)持久性(Durability):是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来的其他操作和数据库故障不应该对其有任何影响。即一旦一个事务提交,DBMS(Database Management System)保证它对数据库中数据的改变应该是永久性的,持久性通过数据库备份和恢复来保证。

DBMS采用数据库锁机制保证事务隔离性。当多个事务试图对相同的数据进行操作时,只有持有锁的事务才能操作数据,直到前一个事务完成后,后面的事务才有机会对数据进行操作。oracle数据库还使用数据版本的机制,在回滚段为数据的每个变话都保存一个版本,使数据的更改不影响数据的读取。

二、数据并发问题

并发方式访问数据库会带来并发问题:3种数据库读问题(脏读、不可重复读、幻读),2种数据更新问题。

1)幻想读:事务T1读取一条指定where条件的语句,返回结果集。此时事务T2插入一行新记录,恰好满足T1的where条件。然后T1使用相同的条件再次查询,结果集中可以看到T2插入的记录,这条新纪录就是幻想。

2)不可重复读取:事务T1读取一行记录,紧接着事务T2修改了T1刚刚读取的记录,然后T1再次查询,发现与第一次读取的记录不同,这称为不可重复读。

3)脏读:事务T1更新了一行记录,还未提交所做的修改,这个T2读取了更新后的数据,然后T1执行回滚操作,取消刚才的修改,所以T2所读取的行就无效,也就是脏数据。

幻象读和不可重复读是两个容易混淆的概念,前者是指读到其他已经提交事务的新增数据,后者是指读到已经提交事务的更改数据(更改和删除),为了避免两种情况,采取的对策是不同的,防止读取到更改数据,只需要对操作的数据添加行级锁,阻止操作中数据的变化,而防止读取到新增数据,则往往需要添加表级锁——将整个表锁定,防止新增数据。(oracle使用多版本数据的实现方式)

三、数据库锁机制

数据库采用锁机制解决并发问题。按锁定的对象分为表锁定和行锁定;按并发事务锁定的关系分为共享锁定和独占锁定。

oracle数据库常用的5种锁定:

1)行共享锁定:通过SELECT FOR UPDATE或 LOCK TABLE IN ROW SHARE MODE获取行共享锁定。行共享锁定不防止对数据行进行更改的操作,但可以防止其他会话获取独占数据表锁定。

2)行独占锁定:通过INSERT UPDATE DELETE或LOCK TABLE IN ROW EXCLUSIVE MODE,防止其他会话获取一个共享锁定、共享行独占锁或独占锁定。

3)表共享锁定:通过 LOCK TABLE IN SHARE MODE获取

4)表共享行独占:通过LOCK TABLE IN SHARE ROW EXCLUSIVE MODE获取

5)表独占:通过LOCK TABLE IN EXCLUSIVE MODE获取

四、事务隔离级别

SQL标准定义了以下4种事务隔离级别

数据库事务基础知识

Oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。所以Oracle不支持脏读

SQL标准所定义的默认事务隔离级别是SERIALIZABLE,但是Oracle 默认使用的是READ COMMITTED

设置隔离级别使用 SET TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]

下面是oracle 设置SERIALIZABLE隔离级别一个示例:

数据库事务基础知识

左面是事务T1,右面是事务T2,因为T2级别为SERIALIZABLE,所以即使事务T1在提交了数据之后,事务T2还是看不到T1提交的数据,幻想读和不可重复读都不允许了。

那如何能查看到T1新增的记录呢? 上面T1和T2是并发执行,在T1执行insert的时候事务T2已经开始了,因为T2级别是SERIALIZABLE,所以T2所查询的数据集是T2事务开始前数据库的数据。即事务T1在事务T2开始之后的insert和update操作的影响都不会影响事务T2。现在重新开启一个事务T3 就可以看到T1新增的记录了。

当下列事件发生时,事务就开始了:

1、连接到数据库,并执行第一条DML语句

2、前一个事务结束后,又输入了另一条DML语句



转载于:https://my.oschina.net/elain/blog/387762

相关文章: