前言
好些天,没有更新这个系列了。最近工作出差,而且在几个城市走来走去,在而且是自己也在学习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
这个事务是默认级别的事务,即会读取其他事务已经提交的事务。