初识jdbc对oracle数据库事务处理(隔离级别)

来源:互联网 发布:淘宝大闸蟹资质认证 编辑:程序博客网 时间:2024/05/01 09:52

一项事务是由一条或是多条表达式所组成的一个不可分割的工作单元。我们通过提

交commit()或是回退rollback()来结束事务的操作。

    在JDBC中,事务操作默认是自动提交。也就是说,一条对数据库的更新表达式代表

一项事务操作。操作成功后,系统将自动调用commit()来提交,否则将调用rollback()

来回退。

    其次,在JDBC中,可以通过调用setAutoCommit(false)来禁止自动提交。之后就可

以把多个数据库操作的表达式作为一个事务,在操作完成后调用commit()来进行整体提

交。倘若其中一个表达式操作失败,都不会执行到commit(),并且将产生响应的异常。

此时就可以在异常捕获时调用rollback()进行回退。这样做可以保持多次更新操作后,

相关数据的一致性。
jdbc api提供了5种数据库事务隔离操作:
static int TRANSACTION_NONE = 0;

static int TRANSACTION_READ_UNCOMMITTED = 1;

static int TRANSACTION_READ_COMMITTED = 2;

static int TRANSACTION_REPEATABLE_READ = 4;

static int TRANSACTION_SERIALIZABLE = 8;

下面介绍数据库中发生数据不一致的四个概念:

“脏”数据读写(Dirty Reads):当一个事务修改了某一数据行的值而未提交时,另一事

务读取了此行值。倘若前一事务发生了回退,则后一事务将得到一个无效的值(“脏”数

据)。(这个会发生的条件一直没明白,一个事务未提交的话,另一个事务只能取到原来

的值,不可能取到更新过的未提交的数据(就算事务自动提交,那也是提交了,也不可能

回滚了啊,除非回滚到commit之前的savepoint,那是有可能的)。有谁知道,请麻烦告

诉我一下,发生脏数据读写的前提条件?)

不可重复读写(non-Repeatable Reads):当一个事务在读取某一数据行时,另一事务同

时在修改此数据行,并进行了commit。则前一事务在重复读取此行时将得到一个不一致的

值。

错误(映像)读写(Phantom Reads):当一个事务在某一表中进行数据查询时,另一事务恰

好插入了满足了查询条件的数据行。则前一事务在重复读取满足条件的值时,将得到一

个额外的“影像”值。

丢失更新:有两个事务都对同一条记录进行了读取,然后第一个事务进行修改了先进行

commit,第二个事务后修改进行commit,这样前一个事务的更新就丢失了。(这个最难解决的)

用jdbc进行设置事务隔离级别的时候,要注意,数据库及其驱动程序必须得支持相应的

事务操作操作才行。我在对oracle数据库进行操作的时候,发现

TRANSACTION_REPEATABLE_READ,TRANSACTION_READ_UNCOMMITTED这2个事务无效,不知

道如何把它们打开?
jdbc提供了2个接口函数来设置事务隔离级别和获取当前的事务隔离级别:
setTransactionIsolation
getTransactionIsolation

上述5个事务隔离级别随着值的增加,其事务的独立性增加,更能有效地防止事务操作之

间的冲突,同时也增加了加锁的开销,降低了用户之间访问数据库的并发性,程序的运

行效率也会随之降低。因此得平衡程序运行效率和数据一致性之间的冲突。

一般来说,对于只涉及到数据库的查询操作时,可以采TRANSACTION_READ_UNCOMMITTED

方式;对于防止脏读(有待明确脏读的确切发生条件,概念),可以采用

TRANSACTION_READ_COMMITTED方式;对于防止脏读和不可重复读,可以采用

TRANSACTION_REPEATABLE_READ;在数据一致性要求更的场合再考虑最后一项,由于涉及

到表加锁(没验证过),因此会对程序运行效率产生较大的影响。

对于最后一个事务隔离级别:TRANSACTION_SERIALIZABLE。我的试验结果是,事务之间

是串行执行的,除了select语句。这样上面的4种不一致都可以避免,但是这个级别的开

销很大,具体多大我没试验。
事务1            事务2
select          
                 select
update
                 update(先等着事务1进行提交才能运行)

commit
                 抛8177错误(事务1commit后运行update失败,就是说事务有交叉,不

                           允许更新)
但是如果事务2仅有读取操作,那是可以交叉的,不影响数据的一致性。

另外,在Oracle中数据库驱动对事务处理的默认值是TRANSACTION_NONE,即不支持事务

操作,所以需要在程序中手动进行设置。

最后,本人觉得之前提到的4种数据不一致的问题,在数据库并发中是必然存在的,解决

前3种用一般的事务隔离理论上是可以的,但是要解决丢失更新,事务隔离必须要到

TRANSACTION_SERIALIZABLE,这个损失的效率有待进一步去确认。另外还有2种解决办法

,当要对读取的数据可能进行更新修改时,都一律用select...for update。但这样的话

又容易出现死锁(事务1对表a进行了for update之后要对表b操作for update,而事务2对

表b进行了for update,要对表a进行for update,但都没有进行事务提交,都还是锁定

状态,所以就产生了死锁);读取时只用select,当要更新时,在where条件里把select

到的值也添加进去,进行校验,这个是相对来说比较妥当的解决办法。

目前我对于数据库锁的概念理解还不是很深刻,还在积累经验,学习中。要是自己能手

工加入锁,可以锁住后不让其他事务进行select的就好了?
 

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 猫吃了牛油果怎么办 苹果手机死机开不了机怎么办 新生儿出生第一天没奶水怎么办 第一天断奶奶水一直流出怎么办 3岁宝宝不长个子怎么办 5个月宝宝不长个怎么办 孩子比同龄人矮很多怎么办 孕妇做春梦宫缩怎么办 减肥掉头发很厉害怎么办 孕妇吃了金枪鱼罐头怎么办 怀孕吃了烂水果怎么办 快递水果压坏了怎么办 谈对象被骗了钱怎么办 如果遇到半夜坏人敲门怎么办 小孩晚上不进房间睡觉怎么办 房子照不到阳光潮湿怎么办 4个月婴儿不拉屎怎么办 小孩六个月奶不够吃怎么办 到晚上就没奶水怎么办 20多天奶水不够怎么办 四个月奶不够吃怎么办 7个月宝宝不肯吃东西怎么办 6个月宝宝不肯吃东西怎么办 十一个月宝宝不肯吃东西怎么办 九个月宝宝不肯吃辅食怎么办 八个月宝宝不肯吃辅食怎么办 七个月宝宝不肯吃辅食怎么办 7个月宝不吃辅食怎么办 在月子里奶不够怎么办 8月宝宝不吃辅食怎么办 8个月不吃辅食怎么办 宝宝不吃药怎么办一岁 奶水不足宝宝又不吃奶粉怎么办 一岁婴儿突然不吃饭怎么办 一岁宝宝突然不吃饭怎么办 一岁半宝宝突然不爱吃饭怎么办 1岁宝宝突然不爱吃饭怎么办 一岁多宝宝突然不爱吃饭怎么办 一岁半宝宝突然不吃饭怎么办 八个月宝宝不吃奶粉怎么办 小孩铅超标怎么办如何排铅