在数据库里创建了一个 定时服务,每隔5秒就执行一个存储过程,存储过程会用到游标去执行另一个存储过程,这个存储过程涉及到几表,会有一些 update,select,insert动作,这样是不是很容易会死锁?怎么避免?能够改变锁的范围吗,只锁定某一行的数据?

解决方案 »

  1.   

    死锁发生的可能性很小的。oracle自动在DML操作行上加锁
      

  2.   

    对于程序员而言,如果你作到了事务正常/异常结束后,进行了commit/rollback,剩下的死锁问题就由Oracle解决。在上述前提下,对于Oracle而言,死锁的概率还是非常小的。通常死锁的情形是两种:(1)没有commit/rollback。(2)在一个长事务中,不能commit/rollback。对于后一种情形,程序员应该尽量设法避免。锁的粒度是RDBMS决定的。Oracle提供行级锁。如果你的update只更新一条记录,基本就是使用的行级锁。死锁通常发生在两个独立的进程/线程之间,准确的说是两个事务之间,和是否使用存储过程嵌套、是否使用游标没有关系,有关系的只是事务完成的时间(忘记commit/rollback的本质就是事务变成了一个长事务而已)。因此,避免Oracle死锁两个主要手段:
    (1)尽量设计短事务
    (2)记得commit/rollback
      

  3.   


    LZ应该去看看X.S锁协议,或者X、S加共享锁协议。只有在某人使用的了X锁(update、insert、delete等),才会锁住记录或者表,表现为事务记录。如果另外一个人要操作,与之冲突,数据库会让事务等待该锁释放后再执行,这并不会构成死锁。如果第一个获得X锁的人一直不释放,则另外一个试图获得X锁人就必须一直等待。因此,假如前面的所说的两个人分别以两个程序表示,如果程序中在update/insert/delete之后执行了commit/rollback,则只有数据库出错的情况下才会出现死锁。对于Oracle而言,这种概率是非常低的。如果不是程序对数据库进行操作,比如有人用toad进行了update、insert、delete操作,同时又没有commit/rollback,这时另一个人/程序对该表进行操作时,则很可能会碰到“死锁”状态。这里所谓的死锁其实是等待X锁资源释放。如果只是读操作select,则不论多少人/程序同时操作,都不会产生死锁。
      

  4.   

    oracle不需要显式的begin transaction....,所以一般情况下是不需要的,除非你有很特殊的业务需求。只需要在做完后commit/rollback就可以了
      

  5.   

    wqkjj
    多谢你的建议,结贴。