UPDATE employees                    UPDATE employees   
SET salary = salary x 1.1           SET salary = salary x 1.1
WHERE employee_id = 1000;           WHERE employee_id = 2000;         
UPDATE employees                    UPDATE employees
SET manager = 1342                  SET manager = 1342
WHERE employee_id = 2000;           WHERE employee_id = 1000;比如象这样情况下,会发生DEADLOCK.此时系统应该会自动检查到它并解决它.
那么,系统是怎样解决的呢? 系统如何判断该回退哪个用户的语句呢?
 

解决方案 »

  1.   

    系统确实能够自动检测死锁,并提出警告。但是,它并不主动回退用户的语句,而是直接撤掉用户的最后一次操作。
    但是在之前的操作并不会撤掉,需要用户主动commit或者rollback来完成操作用户1:
    SQL> update st_course set grade=grade+1 where cno = 1;已更新 1 行。SQL> update st_course set grade=grade+2 where cno=2;
    update st_course set grade=grade+2 where cno=2
           *
    ERROR 位于第 1 行:
    ORA-00060: 等待资源时检测到死锁
    SQL> select * from st_course;       SNO        CNO      GRADE
    ---------- ---------- ----------
       2007001          1         93
       2007001          2         85
       2007001          3         88
       2007002          2         90
       2007002          3         80用户2:
    SQL> update st_course set grade=grade+3 where cno = 2;已更新2行。SQL> update st_course set grade=grade+4 where cno = 1;
    update st_course set grade=grade+4 where cno = 1
           *
    ERROR 位于第 1 行:
    ORA-00060: 等待资源时检测到死锁
    SQL> select * from st_course;       SNO        CNO      GRADE
    ---------- ---------- ----------
       2007001          1         92
       2007001          2         88
       2007001          3         88
       2007002          2         93
       2007002          3         80
    在之后,用户1或者用户2执行commit以后,他们的第一个更新操作都会生效,但是第二个形成死锁的就失败了。不管怎样,用户必须手动commit或rollback来完成操作。
      

  2.   

    那你意思就是用户1和2的第2个UPDATE的操作都会失败.
    然后必须由两个用户之一执行提交或回退而使另外一个用户的操作可以成功.
    那么你有没有想过这种情况,如果在两个用户的第2个操作都失败后,他们并不知道这是造成了死锁,而是继续进行更新操作 ,那么就又会造成死锁.完了就又是操作失败.........如此循环下去
    是不是该有DBA来通知这两个用户要提交或回退他们的第1个操作呢?
      

  3.   

    就按楼主的例子,执行结果是这样的:会话1的第二条语句会被ORACLE系统自动的撤销,而此时,会话1也会得到ORACLE系统给出的错误提示,而这时,会话2依然处于等待锁资源的状态.
    如果这时会话1执行ROLLBACK,则会话1的第一条SQL语句会被ROLLBACK .如果执行的是COMMIT语句的话,则会话1的第一条SQL语句会被提交.只有在会话1执行了(ROLLBACK/COMMIT)之后,会话2才能得到相应的锁资源,进行处于可操作的状态.而会话2的两条SQL语句都在等待用户的事务操作语句(ROLLBACK/COMMIT),如果会话2执行ROLLBACK ,则会话2的两条SQL语句都被ROLLBACK ,而如果
    会话2执行的是COMMIT语句,则会话2的两条语句都会被提交.
      

  4.   

    我开发这么多年,就没见过你这样的情况。出现了,就是你的代码错误。更改代码,关DBA什么事情。
      

  5.   

    难道有问题还不允许询问么?再说本身属于db的范畴,问一下db的处理方式也不对么?
      

  6.   

    当然关DBA的事情了。身为DBA,你就是有职责保持数据库始终运行在一个可靠,高效的环境当中。
    出了问题虽然不是你的错,可起码你有职责通知该用户进行改正,不然仍然会造成死锁而是更多的用户无法进行正常的工作