代码改变世界

跟我一起学Oracle 11g【11】----Oracle 中的事务

2013-05-04 14:52  随风浪迹天涯  阅读(2936)  评论(5编辑  收藏  举报

前言

好些天,没有更新这个系列了。最近工作出差,而且在几个城市走来走去,在而且是自己也在学习Spring.Net,所以时间比较少呢!但,不管怎么样,我都会把这个系列更新完成。

5.1节过了,祝大家节后快乐。

1。什么是数据库事务

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作。 事务处理可以确保除非事务性单元内的所有操作都成功完成,否则不会永久更新面向数据的资源。通过将一组相关操作组合为一个要么全部成功要么全部失败的单元,可以简化错误恢复并使应用程序更加可靠。---【来自百度百科】

2。事务的特点

  • 原子性(atomicity)

  事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

  • 一致性(consistency)

  事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。

  • 隔离性(isolation)

  由并发事务所作的修改必须与任何其它并发事务所作的修改隔离,也就是多个事务可以同时进行,互相不产生影响。

  • 持久性(durability)

  事务完成之后,它对于系统的影响是永久性的。该修改即使出现致命的系统故障也将一直保持。

3.事务保存点(Savepoint)

保存点提供了一种机制,用于回滚部分事务。

语法:

savepoint 事务名

 保存点有什么作用呢?作用非常的大呢。

比如,有一个数据库管理员,在早上的时候,设置了一个保存点a1,然后工作(对数据库进行增删改查),到了中午他又设置了一个保存点a2,到了下午他又继续工作(还是对数据库进行增删改查),然后到了晚上。突然之间,他执行了一个很愚蠢的操作,把数据库里的数据全部给删除了!!!!

那这个时候怎么办呢?好在他在早上和中午的时候设置了保存点,然后只要回到保存点就可以了。

【例】在我的scott用户下面。对emp表设置一个事务,然后删除一条数据,最后在回滚事务。

设置一个事务,如下图:

然后我们队数据进行插入一条数据,

insert into emp values(8888,'Lanny','CLEAK',7782,to_date('2012-10-10','yyyy-mm-dd'),1000,100,20);

现在scott用户下面的emp表已经有15条数据了。

5。回滚事务(rollback)

那如果我们现在撤销刚刚的操作怎么办呢?这个就需要回滚事务了。事务回滚是指将该事务已经完成的对数据库的更新操作撤销。

语法:

rollback to 事务名 --撤销单个事务

or

rollback   --如果后面不加事务名,则撤销所有存在的事务

【例】我们撤销刚新加入进去的Lanny用户。

6。事务的提交(commit)

事务的提交指的是把你刚刚操作的数据真正的写入到数据库中,这个时候 你就不能在运用rollback进行撤销你刚才的操作了。

语法:

commit

【例】先设置一个保存点,然后往emp里插入一条数据,接着提交事务。

①设置一个保存点

savepoint mySave2;

②插入数据

insert into emp values(9999,'Good','CLEAK',7782,to_date('2012-10-10','yyyy-mm-dd'),1000,100,20);

③提交事务

④测试回滚

OK,那这个时候,如果我在回滚到mySave2这个保存点可以吗?我们操作,得到如下错误:

为什么呢?因为数据库一旦commit了数据,那么就会撤销所有的保存点。所以,你会得到这么一个错误哦。

7。Oracle事务的一些属性

7.1只读事务(read only)

只读事务,只运行执行查询操作,而不允许执行DML(删除、增加、修改)操作,使用只读事务,使得用户可以只取到某个时间点的数据。

假如有一个机票代售点,有一个管理员想在一个时间点进行统计总共卖出去的数量,这个时候可以使用只读事务。设置了只读事务之后,尽管有其它的对话产生,但是只读事务不会去去取最新的事务的变化,从而可以保证一个时间点只取到需要的数据。

语法:

set transaction read only

【例】设置system用户下的只读事务

刚开始我们用system 用户登录,然后设置只读事务,如下图:

我用select * from scott.emp;这个语句查看了scott用户下的emp表里的数据是14条。

ok,我现在在打开一个 PL/SQL developer,这一次我用scott这个用户登录进去。进去之后,我往scott用户的emp里插入一条数据,如下:

insert into emp values(8888,'Lanny','CLEAK',7782,to_date('2012-10-10','yyyy-mm-dd'),1000,100,20);

目前,scott用户下的emp表的数据是:

不意外的知道 数据有15条。

但是如果我们在回到system用户下面的数据是多少条呢?用select * from scott.emp; 这个语句进行查询,我们发现,我们依然得到的是14条数据。

上面的例子就是只读事务。在system用户下面,它设置了只读事务,所以它只获取到以前的值,而不会获取更新后的数值。

7.1读写属性 read write

可以将事务设置为可读、可写的状态,其实这也就是事务的默认状态。所以,改属性的设置,并没有多大的现实意义。可不不给与考虑。

语法很简单:

set transaction read write

不过,需要注意的是:一旦设定了set transcation read write命令,那么该命令之前就不能出现set transaction命令之外的其它命令了。

 

如果你像上面一样,你重新设定一遍 read write ,这样是不行滴。

7.3 serializable隔离级别

serializable隔离级别指的是串行化事务。串行化事务和只读(read only)事务实现相同的功能---隔离其它事务对数据库的影响。但是串行化事务允许在其中执行任何的DML操作,比如增、删、改、查。。。

我们现在还没有进行serializable的设置,ok,我们测试一下。

①我们现在新增一条数据进emp表中,并且 我还进行了commit 操作。

insert into emp values(8888,'Lanny','clerk',7782,to_date('2001-5-21','yyyy-mm-dd'),2000,100,10);

②ok,我们重新运行一个 PL/SQL Development(注意:打开2个命令窗口,没法测试)

现在,我们有2个 PL/SQL Development了。

③我们在新建的PL/SQL Development里进行查询,和我先前得到的结果是一样的,这并没让我们产生惊喜。

不出意外的得到了我们新插入的值。

好的,那现在我们进行个serializable操作,看看结果会怎么样。。

①serialization的命令如下

set transaction isolation level serializable;

②ok,我们现在在新建的PL/SQL Development 新增一条数据,如下:

请注意,我已经用commit,把事务给提交了。

我们查一下数据:

③我们在回到我们初次打开的窗口,进行查询,结果如下

我们没有得到我们刚插入的数据,这就是serializable的作用。

7.4 read  commit

这个事务是默认级别的事务,即会读取其他事务已经提交的事务。