| SQL> create table t(id number,nick varchar2(32),status number,email varchar2(32),gmt_modified date);
Table created. SQL> desc t; SQL> begin PL/SQL procedure successfully completed. SQL> alter session set nls_date_format='YYYY-MM-DD HH24:MI:SS'; Session altered. SQL> select * from t; ID NICK STATUS EMAIL GMT_MODIFIED 1 row updated. SQL> select * from t; ID NICK STATUS EMAIL GMT_MODIFIED --session 2也执行这样的语句,出现等待。 --session 1提交 --session 2执行完成,查看结果 ID NICK STATUS EMAIL GMT_MODIFIED |
上面运行的更新语句
| update t set status=1,gmt_modified=sysdate where id in ( select id from (select id from t where nick='test' and status=0 order by id asc) where rownum < 2) and status=0; --注意此条件 |
当session 1执行,但并不提交后,session 2执行相同的语句,由于update语句中有select子查询,众所周知,select要进行一致性读,即也会读取到记录1,但这又是一个update语句,会进行当前读,session 2也想去更新这一行,但发现这一行已被另外一个事务更新,所以出现等待。但当session 1提交后,通过以上实验,证明session 2会再次触发一致性读与当前读,去更新了满足条件的第二行,而不是第一行。
大家还可以做其它实验,比如说session 1执行如下的语句:
| update t set status=1,gmt_modified=sysdate where id in ( select id from (select id from t where nick='test' and status=0 order by id asc) where rownum < 2) and status=0; --注意此条件 |
session 2执行如下的语句:
| update t set status=1,gmt_modified=sysdate where id in ( select id from (select id from t where nick='test' and status=0 order by id asc) where rownum < 4) and status=0; --注意此条件 |
结果是sesion 1更新了1条;session 2更新了2条,而session 2实际想更新3条。
本篇实验也提供了一个很好处理并发的方法,使用此方法,可以保证多个更新在并发时不会更新同一行,不过要在更新后,加一个判断,如果实际更新的条数 != 想要更新的条数(即sql语句中的rownum),那就说明出现了并发,并且剩余的满足条件的记录数不满足应用要求,这时候就需要在应用层加上进一步的并发处理了。我们在实际中出现的一个案例,恰好就是没有对实际更新的条目进行判断,导致出现了应用层数据逻辑错误。
相关专题
- 综合布线工程案例 (2705篇文章)
- Oracle数据库中关键字 (67次浏览)
- 实例讲解清除Oracle 10g RAC CRS的方法 (48次浏览)
- Data Guard学习物理standby高级管理 (47次浏览)
- 实例讲解Oracle表碎片的具体起因及解决办法 (38次浏览)
- 深入讲解“database link”的设置和使用 (31次浏览)
- 甲骨文:从手机功能变化看数据库性能扩展 (27次浏览)
- Windows环境中同时安装Oracle9i 10g和11g (25次浏览)
- Oralce定时执行存储过程任务的设置步骤 (24次浏览)
- 实例讲解Oracle监听口令及监听器安全 (23次浏览)
- 测量磁盘I/O (21次浏览)



