本帖最后由 delphisanding1 于 2011-05-14 13:51:55 编辑

解决方案 »

  1.   

    锁的主要目的是执串行操作。oracle更新时,在行上加排它锁,在表上加行级排它锁,更新锁定的最小单位是数据行。
    你举例的两语句条件不一样,不会更新相同的数据行。所以不存在A操作阻塞B操作。
    如果两操作更新相同的数据行,则B操作必须等待A操作事务提交或回滚。
      

  2.   


    /*从数据库概念的角度
    锁机制是为了实现对数据访问的可串行化
    通常意义上有共享锁(share lock),和排它锁(exclusive lock),也叫独占锁;
    1.共享锁
    如果A事物对数据加了共享锁,那么所有的事物只能读取该数据,不能写该数据,
    如果事物B要想对该数据进行写操作,那么就得等到A事物释放s锁,
    然后B事物对数据加x锁,B事物对数据加x锁后,其他的所有事物想对数据进行的操作(读和写),
    都将处于排队等待状态,直到B事物操作完成,并提交;
    2.独占锁
    如果C事物对数据D2加了x锁,那么事物C将会阻塞所有的对数据D2进行访问的事物,
    直到C事物释放对数据D2加的x锁为止。从Oracle角度
    锁机制是用于管理对共享资源的并发访问。
    oracle中是锁类型有:
          DML锁
          DDL锁
          闩
          手动锁定和用户定义锁
    具体请参考Thomas Kyte的经典书籍<<...编程艺术>>
    锁和数据库的并发控制有非常紧密的联系;对于你上面的两个update操作:
    A,B操作都是更新相同的数据,因为A先申请更新表,所以A先锁定表,
    用户B只能等待A操作完成之后才能进行,*/
    session a:
    15:30:11 SQL> select * from t;
             ID
    -----------
            101
            102
            103
            10415:30:16 SQL> update t set id=1001 where id=101;
    1 row updated15:31:23 SQL> commit;
    Commit complete15:31:47 SQL> update t set id=1002 where id=102;
    1 row updated15:32:16 SQL> commit;
    Commit completesesion b:
    15:33:03 SQL> select * from t;
             ID
    -----------
           1001
           1002
            103
            104
    --
    session a:
    15:32:51 SQL> select * from t;         ID
    -----------
           1001
           1002
            103
            104
    --
    --下面我们来看看同时update有什么情况:
    session a:
    15:35:03 SQL> update t set id=100000003 where id=103;
    1 row updated
    15:36:22 SQL> --我们这里并未提交
    15:37:03 SQL> --所以session b将会一直处于等待状态
    session b:
    --就停止在这里,一直等待session a的提交:
    15:33:09 SQL> update t set id=1000003 where id=103;session a:
    15:37:26 SQL> commit;--我们提交了
    Commit complete
    15:38:37 SQL> --下面看看session b将会是什么一个状态
    session b:
    15:33:09 SQL> update t set id=1000003 where id=103;
    0 rows updated
    15:38:37 SQL> 
    /*
    奇怪了,我们明明发出了update语句了,怎么提示我们更新0行呢?
    其实这是oracle为了实现并发访问而设置的隔离级别;
    session b读取到了脏数据(其他会话或者事物未提交的数据),所以更新失败了;
    */
      

  3.   

    上面的操作看上去时间有些错误,session b发生在session a之前,
    其实我在操作的时候是session a发生在session b之前;可能是PL/SQL Developer的原因,都被告诫了要多用SQL Plus做测试,哎......