如题

解决方案 »

  1.   

    回复人: mbzdh(一天一个进步) ( ) 信誉:96  2004-09-23 16:25:00  得分: 0  
     
     
       楼上的什么意思,说详细点,我一同事说,存储过程就能解决 冲突的问题,他说,如果多用户同事调用这个存储过程,存储过程会给他们排队,不知正确否?
     
     
    ---------------对的!
      

  2.   

    >>-- 我一同事说,存储过程就能解决 冲突的问题,他说,如果多用户同事调用这个存储过程,存储过程会给他们排队,不知正确否?
       存储过程给调用者排队,第一次听说。
       存储过程是在数据库服务端执行的代码,采用预编译技术。如果存储过程就能解决 冲突的问题问题,不要数据库的自旋锁了,事务也没社么意义,全用存储过程解决算了,为何SQL中还有start 事务;end 事务;这样的语句了。
      

  3.   

    有可能会,
    比如存储过程执行A                                    B
    修改 AA第一条记录                    修改AA第二条记录
    其它处理。。
    修改AA第二条记录                     修改 AA第一条记录在这里就可能造成死锁,
    因为A在等待B中修改AA的第二条记录,而B在等待A释放AA的第一条记录,
    相互锁主了资源
      

  4.   

    回复人: riding(ride)我也比较同意你的看法,可好象我同事很肯定似的,我是没见到过相关的资料说存储过程有这个功能。
      

  5.   

    tw_cshn(一无所有) 
    很明显,你举的例子的确可以说明问题,但是事实上,一个优秀的数据库编程人员处理这种问题的时候会尽量避免出现这种结构,因为这是一种极不合理的写法:)
    mbzdh(一天一个进步)
    你同事可能没有表达清楚或者真的就是不怎么了解存储过程,其实,如果使用了事务处理并且避免了不合理的结构那么基本上是不会出现冲突的,更确切的说是死锁问题,当然要完全避免是不可能的,我们可以把死锁情况降低到最小,处理方法 SQL 联机丛书有明确说明
    1、按同一顺序访问对象。
    2、避免事务中的用户交互。
    3、保持事务简短并在一个批处理中。
    4、使用低隔离级别。
    5、使用绑定连接。
    ----------------------------------------------------------------
                 花自飘零水自流,一种相思,两处闲愁。
                   此情无计可消除,才下眉头,又上心头。
    ----------------------------------------------------------------
      

  6.   

    楼主似乎想搞清楚的不是锁的问题,是并发的n个存储过程是否会排队..用事实说话(先抛开锁的问题),不会证明:
    Create PROCEDURE delayTime @@DELAYLENGTH char(9),@i integer
    as
      WAITFOR DELAY @@DELAYLENGTH    --延时
      print @i
    go在查询分析器里打开两个查询,注意是两个,不能在同一个查询里调用两次,应为那样肯定是排队的查询1:exec delayTime '00:00:15',1
      
    查询2:exec delayTime '00:00:01',2先执行1,再执行2,看看哪个先结束
      

  7.   

    你还需要搞清楚隔离级别的问题:
    隔离级别
    当锁定用作并发控制机制时,它可以解决并发问题。这使所有事务得以在彼此完全隔离的环境中运行,但是任何时候都可以有多个正在运行的事务。可串行性是通过运行一组并发事务达到的数据库状态,等同于这组事务按某种顺序连续执行时所达到的数据库状态。 SQL-92 隔离级别
    尽管可串行性对于事务确保数据库中的数据在所有时间内的正确性相当重要,然而许多事务并不总是要求完全的隔离。例如,多个作者工作于同一本书的不同章节。新章节可以在任意时候提交到项目中。但是,对于已经编辑过的章节,没有编辑人员的批准,作者不能对此章节进行任何更改。这样,尽管有未编辑的新章节,但编辑人员仍可以确保在任意时间该书籍项目的正确性。编辑人员可以查看以前编辑的章节以及最近提交的章节。事务准备接受不一致数据的级别称为隔离级别。隔离级别是一个事务必须与其它事务进行隔离的程度。较低的隔离级别可以增加并发,但代价是降低数据的正确性。相反,较高的隔离级别可以确保数据的正确性,但可能对并发产生负面影响。应用程序要求的隔离级别确定了 SQL Server 使用的锁定行为。SQL-92 定义了下列四种隔离级别,SQL Server 支持所有这些隔离级别: 未提交读(事务隔离的最低级别,仅可保证不读取物理损坏的数据)。
    提交读(SQL Server 默认级别)。
    可重复读。
    可串行读(事务隔离的最高级别,事务之间完全隔离)。 
    如果事务在可串行读隔离级别上运行,则可以保证任何并发重叠事务均是串行的。下面四种隔离级别允许不同类型的行为。隔离级别    脏读 不可重复  读取幻像 
    未提交读    是   是        是 
    提交读      否   是        是 
    可重复读    否   否        是 
    可串行读    否   否        否 
    -----------------------------------------------------------------看了上面一段,就知道,事物和锁没有必然联系的,锁只关心提交不提交的问题.存储过程就是一个事物体事物的死锁例子:
    create table test(id int)
    begin tran  --开始事务
    insert test values(1)
    --执行上面的语句,然后新开一个窗口,执行下面的语句:
    select * from test--你会发现已经死锁了. 这里并没有加锁,是sqlserver自动加的
    ------------------------------------------------------------------
      

  8.   

    用waitfor和update,insert,select配合可以演示各种锁
    http://community.csdn.net/Expert/topic/2975/2975937.xml?temp=.7685053
    这就要求你必须在设计阶段注意事物交互,尽量不要设计很大或者费时的模块.在下面的死锁例子中,可以把两个延时加大,然后用
    set lock_timeout 3000
    go
    可以把锁时间控制在3秒之内,注意这个是运行期控制的,同样,其他的例子也可以用
    set lock_timeout来控制请求的时间
    比如上面一帖里把select * from test 前加入set lock_timeout 3000 就可以在3秒后抛出异常--下面是与锁有关的演示  by 邹建--设tb(A,B,C)
    create table #tb(A varchar(2),B varchar(2),C varchar(2))
    insert into #tb
    select 'a1','b1','c1'
    union all select 'a2','b2','c2'
    union all select 'a3','b3','c3'--1)排它锁
    --在第一个连接中执行以下语句
    begin tran
       update #tb
       set A='aa'
       where B='b2'
       waitfor delay '00:00:3'  --等待3秒
    commit tran--在第二个连接中执行以下语句
    begin tran
       select * from #tb
       where B='b2'   
    commit tran
    --若同时执行上述两个语句,则select查询必须等待update执行完毕才能执行即要等待30秒--2)共享锁
    --在第一个连接中执行以下语句
    begin tran
       select * from #tb holdlock --holdlock人为加锁
       where B='b2' 
       waitfor delay '00:00:3'  --等待3秒
    commit tran--在第二个连接中执行以下语句
    begin tran
       select A,C from #tb
       where B='b2' 
       update #tb
       set A='aa'
       where B='b2'   
    commit tran
    --若同时执行上述两个语句,则第二个连接中的select查询可以执行
    --而update必须等待第一个连接中的共享锁结束后才能执行 即要等待30秒--3)死锁
    --增设tb2(D,E)
    create table #tb2(D varchar(2),E varchar(2))
    insert into #tb2
    select 'd1','e1'
    union all select 'd2','e2'--在第一个连接中执行以下语句
    begin tran
       update #tb
       set A='aa'
       where B='b2' 
       waitfor  delay '00:00:5'
       update #tb2
       set D='d5'
       where E='e1' 
    commit tran
       
    --在第二个连接中执行以下语句
    begin tran
       update #tb2
       set D='d5'
       where E='e1' 
       waitfor  delay '00:00:3'
       update #tb
       set A='aa'
       where B='b2'  
    commit tran--删除临时表
    drop table #tb,#tb2--同时执行,系统会检测出死锁,并中止进程
    /*-------------------------------------------------------------
    SET IMPLICIT_TRANSACTIONS  ON --用户每次必须显式提交或回滚。否则当用户断开连接时,
                                  --事务及其所包含的所有数据更改将回滚SET IMPLICIT_TRANSACTIONS  OFF --自动提交模式。在自动提交模式下,如果各个语句成功
                                   --完成则提交。
    ------------------------------------------------------------------------*/
      

  9.   

    搂主的思路可能被你的同事吧概念给混了。首先大型数据库都是自动加锁的,如oracle更改一条用行锁定,添加一批用页,区锁定。当用drop table,create table 这样的语句用表锁定。这样来保证一次更改的完整性,没有脏读。但是在跨表之间的完整性需要事务去解决。这和基于文件的数据库如foxpro 有很大区别,foxpro当有多个用户访问同一表,要明显的加锁。 你的同事那样错误的认为,那是本身语句起作用,并不是因为存储过程,不信你用10个客户端,同时改写一条记录,不会产生冲突的。所以搂住的答案是:存贮过程中对单表改写,不会冲突,如果是多表关联,会冲突,需要将他们放到一个事务内,不知这样解释搂住是否明白。