一种并发控制的精典案例

提供及时全面的经典资源 并发控制一直是个比较头痛的问题,下文演示了一种并发案例,希望大家能从中有所收获。
SQL> create table t(id number,nick varchar2(32),status number,email varchar2(32),gmt_modified date); Table created.
SQL> desc t;
Name                                      Null?    Type
----------------------------------------- -------- ----------------------------
ID                                                 NUM
BER
NICK                                               VARCHAR2(32)
STATUS                                             NUMBER
EM
AIL                                              VARCHAR2(32)
GMT_MODIFIED                                       DATE

SQL> begin   
  2      for i in 1..5
loop
  3           insert into t values(i,'test',0,'test@taobao.com',sysdate);
  4      end loop;
  5      
commit;
  6  end;
  7  /

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 test            0 test@taobao.com     2008-04-09 13:28:27
2 test            0 test@taobao.com     2008-04-09 13:28:27
3 test            0 test@taobao.com     2008-04-09 13:28:27
4 test            0 test@taobao.com     2008-04-09 13:28:27
5 test            0 test@taobao.com     2008-04-09 13:28:27
         
--session 1执行,但不提交         
SQL> update t set status=1,gmt_modified=sysdate where id in (
  2                                         select id from (select id from t where nick='test' and status=0 order by id asc)
  3                                                          where rownum < 2)
                                           and status=0;

1 row updated.
SQL> select * from t;
ID NICK       STATUS EMAIL                GMT_MODIFIED
-- ------ ---------- -------------------- -------------------
1 test            1 test@taobao.com      2008-04-09 13:36:31
2 test            0 test@taobao.com      2008-04-09 13:28:27
3 test            0 test@taobao.com      2008-04-09 13:28:27
4 test            0 test@taobao.com      2008-04-09 13:28:27
5 test            0 test@taobao.com      2008-04-09 13:28:27

--session 2也执行这样的语句,出现等待。
SQL> update t set status=1,gmt_modified=sysdate where id in (
  2                                         select id from (select id from t where nick='test' and status=0 order by id asc)
  3                                                          where rownum < 2)
                                                and status=0;

--session 1提交
commit;

--session 2执行完成,查看结果
SQL> select * from t;

ID NICK      STATUS EMAIL               GMT_MODIFIED
--- ----- ---------- ------------------- -------------------
  1 test           1 test@taobao.com     2008-04-09 13:48:30  --session 1更新了这条
  2 test           1 test@taobao.com     2008-04-09 13:48:37  --session 2更新了这条
  3 test           0 test@taobao.com     2008-04-09 13:28:27
  4 test           0 test@taobao.com     2008-04-09 13:28:27
  5 test           0 test@taobao.com     2008-04-09 13:28:27


上面运行的更新语句
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),那就说明出现了并发,并且剩余的满足条件的记录数不满足应用要求,这时候就需要在应用层加上进一步的并发处理了。我们在实际中出现的一个案例,恰好就是没有对实际更新的条目进行判断,导致出现了应用层数据逻辑错误
我也来说两句 查看全部回复

最新回复

  • sitedir (2008-5-27 20:17:53)

      游戏有外挂并不奇怪,从原理上讲,任何游戏都是可以制作外挂的(如FPE游戏修改至尊)。也就是说,一般二级数据程序员都会修改,官方从技术上堵截外挂是不可能的!我玩过不知道多少网络游戏,看过不少用外挂过外挂,因为我以前是网管,还要帮人下载外挂,但是仅仅就网络游戏而言,我不知道有什么理由让我去用外挂。
      大家总是用完天龙八部外挂了,看到游戏毁了,然后去官方网站骂娘,骂官方无能,不能阻止外挂猖獗.令外挂这么猖獗还不是借中国玩家之手?
      游戏官方赚了不少,你又赚了多少啊?玩游戏你找到了快乐?可能你用外挂挂到了N级 第二天 别人用另一种外挂挂到比你高出N+N级,到时候你是不是还要找到更好的外挂挂到更高级?估计你永远到不了头!外挂已经深深扎根难根治了中国玩家心里,网络游戏有些玩家把级高是就是快乐,根本丧失了本质.不够我习惯了玩游戏的本质是娱乐!

      中国玩家的心理:
      我想每个人都想体会到那种高高再上的王者气概,也许这是用QQ三国外挂的一个动机。还有对金钱的渴望也促使着一些人使用外挂。然而,在得到了这些的同时我们失去了什么呢??加速和腾空让你错过了游戏里的美丽景色和鸟语花香。你甚至不能体会到练级的乐趣。为了一点其实什么都不是的虚拟货币,你生活在网络游戏的底层.
      作为消费群体的奇迹世界外挂玩家们,在被代理商无情剥削之后,也开始慢慢觉醒,一些聪明的玩家开始通过运用黑客技术来寻找游戏的漏洞bug,并利用这些漏洞来为自己在游戏里的人物服务,从最初的在线外挂到后来的脱机外挂,可以说最初玩过〈传奇〉的老玩家都是外挂发展的见证人!那么作为游戏运营商和代理商们,他们对外挂又是持一种什么态度呢?在游戏外挂发展的初期~~尚未触及商家利益的时候,大都持一种默许的态度;后来外挂的发展慢慢开始损害其自身利益时,如穿怪,刷金条外挂,强行交易外挂等恶意外挂的产生后,代理商们坐不住了,利用各种技术进行封堵,以维持游戏的基本平衡。
      网络游戏的外挂:
      我下了很多网络游戏的外挂,只是看了说明。功能无非就是自动打怪,加速,穿墙,挂机,自动练级。我们需要这些吗??至少我不需要,至少我在游戏里都没有靠外挂练级,何必要外挂帮我做这些呢?也许我也需要外挂,在我吃饭的时候,让外挂帮我练练级,到也是不错。可是就为这个,值得冒着被封号的危险用外挂吗??

      中国玩家对征途外挂的态度:
      首先我相信,什么外挂都会泛滥。每个网络游戏都具备外挂泛滥的条件。不用外挂,玩起来一点都不累,是非常好玩的网络游戏,我们为什么要用外挂呢??我们不需要外挂帮我们做什么啊!!网络游戏之所以外挂泛滥,那是因为外挂能把玩家从简单乏味的杀怪练级中解放出来!最初很多中国玩家(这里指普通玩家)在玩网游的时候,可能心里都有这样的美好愿望:能在游戏中扮演一个济世扶危的人物,能结识一帮好友,快意江湖!可在游戏后发现整天为练级,装备而努力,原有的雄心壮志已经在无聊漫长的练级中被消磨怡尽,玩家开始变得易怒和暴躁,为练级的地盘和装备的所有,可以和人大打出手,朋友,亲人都可以反目成仇。当有一天,你忽然发现游戏里其他玩家等级突然提升的很快,打怪练级变得无比轻松的时候;当你发现原来一个个等级低于你的玩家和朋友都超越你的时候;当别人穿上威武的高级装备在你面前耀武扬威的时候,而这一切其实通过外挂等不公平的手段获取的时候,你会作何感受?有的玩家会愤而退出;有的玩家也许很洒脱,毫不在意,你玩你的,我玩我的;但更多的玩家可能会和我一样坚决不使用外挂,对!我使用外挂,但这是大势所趋。当游戏中周围的人,甚至你朋友都在使用魔兽外挂|魔兽世界外挂的时候,你还能做到独善其身吗