本帖最后由 htl258 于 2010-07-15 19:00:55 编辑

解决方案 »

  1.   

    检测死锁如果发生死锁了,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?这时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。SQL Server自带的系统存储过程sp_who和sp_lock也可以用来查找阻塞和死锁, 但没有这里介绍的方法好用。
     use master
    go
    create procedure sp_who_lock
    as
    begin
    declare @spid int,@bl int,
     @intTransactionCountOnEntry  int,
            @intRowcount    int,
            @intCountProperties   int,
            @intCounter    int create table #tmp_lock_who (
     id int identity(1,1),
     spid smallint,
     bl smallint)
     
     IF @@ERROR<>0 RETURN @@ERROR
     
     insert into #tmp_lock_who(spid,bl) select  0 ,blocked
       from (select * from sysprocesses where  blocked>0 ) a 
       where not exists(select * from (select * from sysprocesses where  blocked>0 ) b 
       where a.blocked=spid)
       union select spid,blocked from sysprocesses where  blocked>0 IF @@ERROR<>0 RETURN @@ERROR 
      
    -- 找到临时表的记录数
     select  @intCountProperties = Count(*),@intCounter = 1
     from #tmp_lock_who
     
     IF @@ERROR<>0 RETURN @@ERROR 
     
     if @intCountProperties=0
      select '现在没有阻塞和死锁信息' as message-- 循环开始
    while @intCounter <= @intCountProperties
    begin
    -- 取第一条记录
      select  @spid = spid,@bl = bl
      from #tmp_lock_who where Id = @intCounter 
     begin
      if @spid =0 
                select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'
     else
                select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'
     DBCC INPUTBUFFER (@bl )
     end -- 循环指针下移
     set @intCounter = @intCounter + 1
    enddrop table #tmp_lock_whoreturn 0
    end
     杀死锁和进程如何去手动的杀死进程和锁?最简单的办法,重新启动服务。但是这里要介绍一个存储过程,通过显式的调用,可以杀死进程和锁。use master
    goif exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[p_killspid]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
    drop procedure [dbo].[p_killspid]
    GOcreate proc p_killspid
    @dbname varchar(200)    --要关闭进程的数据库名
    as  
        declare @sql  nvarchar(500)  
        declare @spid nvarchar(20)    declare #tb cursor for
            select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)
        open #tb
        fetch next from #tb into @spid
        while @@fetch_status=0
        begin  
            exec('kill '+@spid)
            fetch next from #tb into @spid
        end  
        close #tb
        deallocate #tb
    go--用法  
    exec p_killspid  'newdbpy'
     查看锁信息如何查看系统中所有锁的详细信息?在企业管理管理器中,我们可以看到一些进程和锁的信息,这里介绍另外一种方法。--查看锁信息
    create table #t(req_spid int,obj_name sysname)declare @s nvarchar(4000)
        ,@rid int,@dbname sysname,@id int,@objname sysnamedeclare tb cursor for 
        select distinct req_spid,dbname=db_name(rsc_dbid),rsc_objid
        from master..syslockinfo where rsc_type in(4,5)
    open tb
    fetch next from tb into @rid,@dbname,@id
    while @@fetch_status=0
    begin
        set @s='select @objname=name from ['+@dbname+']..sysobjects where id=@id'
        exec sp_executesql @s,N'@objname sysname out,@id int',@objname out,@id
        insert into #t values(@rid,@objname)
        fetch next from tb into @rid,@dbname,@id
    end
    close tb
    deallocate tbselect 进程id=a.req_spid
        ,数据库=db_name(rsc_dbid)
        ,类型=case rsc_type when 1 then 'NULL 资源(未使用)'
            when 2 then '数据库'
            when 3 then '文件'
            when 4 then '索引'
            when 5 then '表'
            when 6 then '页'
            when 7 then '键'
            when 8 then '扩展盘区'
            when 9 then 'RID(行 ID)'
            when 10 then '应用程序'
        end
        ,对象id=rsc_objid
        ,对象名=b.obj_name
        ,rsc_indid
     from master..syslockinfo a left join #t b on a.req_spid=b.req_spidgo
    drop table #t参考
      

  2.   

     FROM TB WITH (ROWLOCK)
      

  3.   

    htl258讲得太泛了,
    我都不看得眼花,SQL77
    那个是不是说在select的时候加上(rowlock)?
    这样就可以防止表锁吗?
      

  4.   

    我在存储过程里这样写
    insert into BFS_BusinessInfo with(rowlock) values (.....)
    这个语句是不是把表的锁机制改为行级锁啊,
    这样是不是可以避免表锁的呢?
      

  5.   

    正常来讲,insert时不需要加rowlock,就默认是rowlock了,而锁升级是sql server自己判断去实现的,因为默认锁资源是有限的当锁资源到达限制时,自动将粒度小的锁升级为粒度大的锁,释放资源
      

  6.   

    引用联机:锁升级就是将大量较细粒度的锁(例如行)转换为少量较粗粒度的锁(例如表)。利用锁升级可以减少系统开销。 当事务超出其升级阈值时,Microsoft SQL Server 2005 Mobile Edition (SQL Server Mobile) 会自动将行锁和页锁升级为表锁。在 SQL Server Mobile 中,锁升级可以是从行到表或从页到表,但不能是从行到页。在表级别上升级时,不能请求低于表的锁。 例如,在行上执行表事务时,SQL Server Mobile 会自动在受影响的行上获取锁,同时将更高级别的意向锁置于包含这些行的页和表上。所有相关的索引页也将同时锁定。当事务所持有的锁的数量超出其阈值时,SQL Server Mobile 就会尝试将表上的意向锁更改为更强的锁。例如,意向排他 (IX) 锁可以更改为排他 (X) 锁。得到更强的锁后,事务在表上所持有的所有页级及行级锁都将予以释放。如果请求锁时超出特定的锁升级阈值,锁就会按各个表分别进行升级。对于所有子表级的锁而言,不管类型如何,都将计入阈值统计。升级阈值应仅视为估计值,这是因为内部操作所请求的锁都已计入阈值统计中。升级过程可能会早于预期时间。如果由于锁冲突而导致无法进行升级,事务仍将继续,但可能会在以后尝试重新进行升级。注意:  
    除非属于临时表锁,否则意向锁、行锁和页锁都将计入升级统计中。当特定表上意向锁、行锁和页锁的总数超出升级阈值时,就会进行升级。
     
    您可以通过设置锁升级阈值来控制每个会话的锁升级,如以下代码示例所示:SET LOCK_ESCALATION 1000; 此设置影响数据库中的所有表。默认值为 100。
      

  7.   

    那到底是怎么样的啊?
    原来的存储过程里就是没有 with(rowlock)这个语句,
    所以当有两笔数据同时过来插入数据库时,
    总会有其中的一笔是因为死锁而处理失败,
    另外一笔处理成功,
    我就想是不是因为sqlserver是默认的表锁,当有多笔数据过来插入数据库时,其中两笔同时插入,其中一笔插入时,启用了表锁,所以另外一笔就失败了?
    我加个with(rowlock)可不可以解决这个问题呢?USE BFSDB
    IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'up_InsertBFSBusinessInfo')
    BEGIN
    DROP  Procedure  up_InsertBFSBusinessInfo
    ENDGO/******************************************************************************
    ** File: up_InsertBFSBusinessInfo.Sql
    ** Name: up_InsertBFSBusinessInfo
    ** Desc: 添加CPC请求的业务信息
    ** Return Value:
    **
    ** Auth: 
    ** Date: 2008-04-23
    *******************************************************************************
    ** Change History
    *******************************************************************************
    ** Date: Author: Description:
    ** -------- -------- ---------------------------------------
    **    
    *******************************************************************************/
    CREATE Procedure up_InsertBFSBusinessInfo
    (
    @BusinessGuid varchar(50) , -- 系统内部编号
    @CPCXmlData text , -- CPC报文数据
    @TransCode varchar(4) , -- 交易码
    @InitBranchId varchar(4) , -- 流程发起机构号
    @InitUserId varchar(8) , -- 流程发起柜员号
    @TransactionDate varchar(20) , -- 当前日期
    @BusinessId varchar(20) , -- 业务流水号
    @BusinessType varchar(5) , -- 业务种类
    @BusinessInitBranchId varchar(4) , -- 业务发起机构号
    @ExchangeDate varchar(8) , -- 交换日期
    @ExchangeRound varchar(1) , -- 交换场次
    @ImageFilePath varchar(100) , -- 影像路径
    @ImageFileName varchar(1000) , -- 影像名称
    @CurrencyType varchar(3) , -- 币种
    @VoucherType varchar(2), -- 票据种类
    @VoucherNo varchar(12) , -- 票据号码
    @PayeeAccountNo varchar(32) , -- 收款人账号
    @PayeeFullName varchar(62) , -- 收款人名称
    @PayerAccountNo varchar(32) , -- 出票人账号
    @PayerFullName varchar(62) , -- 出票人名称
    @Amount decimal(18,2) , -- 金额
    @VoucherIssueDate varchar(8) , -- 出票日期
    @PaymentCode varchar(16) , -- 支付密码
    @ExchangeBranchId varchar(12) , -- 提出行行号
    @ExchangeInBranchNo varchar(12) , -- 提回行行号
    @PaperFlag varchar(1) , -- 纸票标志
    @Comments varchar(60) , -- 注释
    @MaxEndorseIndex varchar(3) , -- 最大粘单索引
    @SopSSN varchar(12) , -- 柜员流水号
    @ProcessBeginTime datetime, --处理开始时间
    @ProcessEndTime datetime, --处理结束时间
    @ProcessStatus int , -- 处理状态
    @Re text -- 描述
    )AS
    BEGIN TRANSACTION Tran_BFSdeclare @n int
    select @n=count(*) from BFS_BusinessInfo  with (nolock) where  BusinessId= @BusinessIdif (@n>0)
    begin 
      
       --删除已存在的影像存储信息
    delete from  BFS_ImageStoreInfo
    where BusinessGuid=(
    select BusinessGuid from BFS_BusinessInfo  with (nolock) 
    where  BusinessId= @BusinessId )

        --删除已存在的业务信息
    delete from  BFS_BusinessInfo
    where BusinessId=@BusinessId 


    end--添加一条新记录insert into BFS_BusinessInfo
    (
    BusinessGuid,
    CPCXmlData,
    TransCode ,
    InitBranchId,
    InitUserId ,
    TransactionDate ,
    BusinessId ,
    BusinessType ,
    BusinessInitBranchId ,
    ExchangeDate ,
    ExchangeRound ,
    ImageFilePath ,
    ImageFileName,
    CurrencyType,
    VoucherType ,
    VoucherNo ,
    PayeeAccountNo,
    PayeeFullName ,
    PayerAccountNo,
    PayerFullName ,
    Amount,
    VoucherIssueDate ,
    PaymentCode ,
    ExchangeBranchId ,
    ExchangeInBranchNo ,
    PaperFlag ,
    Comments ,
    MaxEndorseIndex ,
    SopSSN ,
    ProcessBeginTime,
    ProcessEndTime,
    ProcessStatus,
    Re )
    values
    (
    @BusinessGuid,
    @CPCXmlData,
    @TransCode ,
    @InitBranchId,
    @InitUserId ,
    @TransactionDate ,
    @BusinessId ,
    @BusinessType ,
    @BusinessInitBranchId ,
    @ExchangeDate ,
    @ExchangeRound ,
    @ImageFilePath ,
    @ImageFileName,
    @CurrencyType,
    @VoucherType ,
    @VoucherNo ,
    @PayeeAccountNo,
    @PayeeFullName ,
    @PayerAccountNo,
    @PayerFullName ,
    @Amount,
    @VoucherIssueDate ,
    @PaymentCode ,
    @ExchangeBranchId ,
    @ExchangeInBranchNo ,
    @PaperFlag ,
    @Comments ,
    @MaxEndorseIndex ,
    @SopSSN ,
    @ProcessBeginTime,
    @ProcessEndTime,
    @ProcessStatus ,
    @Re )

    IF (@@ERROR<>0) 
    ROLLBACK TRANSACTION Tran_BFS 
    ELSE 
    COMMIT TRANSACTION Tran_BFSreturn
    GO
      

  8.   

    利用索引,也能降低锁的级别。
    比如:UPDATE [tb] SET col = 'value' WHERE id = 10086如果id字段上有索引,更新语句支持找到id = 10086的数据,更新锁以及升级后的排它锁都是行级;
    如果id字段上没有索引,更新语句需要扫描表来确定哪些记录需要更新,则更新锁会是表级,尽管排它锁是行级。
      

  9.   

    好的,这个我明白了,但是insert的话,sqlserver默认是表级锁还是行级锁呢?
    我想在insert a with (rowlock) 这样是不是可以把表级锁改为行锁啊?
      

  10.   


    只要修改数据就会有锁定。不是必然导致死锁。两个进程都在等待也未必是死锁,只有两个进程相互等待才是死锁。LZ检查一下BFS_ImageStoreInfo和BFS_BusinessInfo两个表上的索引。
      

  11.   

    BFS_BusinessInfo
    的索引是BusinessId(BusinessId是业务报文的业务流水号。)BFS_ImageStoreInfo
    的索引是BusinessGuid(BusinessGuid是对应BFS_BusinessInfo的系统内部编号,由程序自动生成。)
    这两个索引没什么问题吧?
      

  12.   

    其实,我觉得,问题的重点应该是在于楼主的存储过程里面,既有delete,又有insert,这二者都是X锁或者IX锁。死锁是很容易发生的。可以从业务特点入手,看是否需要delete,或者改用别的方式。
    USE tempdb
    GO/*
    1,INSERT 的锁情况
    */IF OBJECT_ID('tb') IS NOT NULL DROP TABLE TBCREATE TABLE tb
    (
    id int,
    col char(20)
    )BEGIN TRAN IN_TB
    INSERT INTO tb VALUES(1,'33')
    --COMMIT TRAN IN_TB
    /*
    request_session_id resource_database_id resource_associated_entity_id resource_type                                                resource_description                                                                                                                                                                                                                                             request_mode                                                 request_status
    ------------------ -------------------- ----------------------------- ------------------------------------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------ ------------------------------------------------------------
    55                 2                    1873497446010978304           RID                                                          1:173:0                                                                                                                                                                                                                                                          X                                                            GRANT
    55                 2                    1873497446010978304           PAGE                                                         1:173                                                                                                                                                                                                                                                            IX                                                           GRANT
    55                 2                    309576141                     OBJECT                                                                                                                                                                                                                                                                                                                        IX                                                           GRANT
    55                 2                    325576198                     OBJECT                                                                                                                                                                                                                                                                                                                        IX                                                           GRANT
    *//*
    2,DELTE 的锁情况
    */BEGIN TRAN DE_TB
    DELETE FROM tb WHERE ID=1
    /*

    request_session_id resource_database_id resource_associated_entity_id resource_type                                                resource_description                                                                                                                                                                                                                                             request_mode                                                 request_status
    ------------------ -------------------- ----------------------------- ------------------------------------------------------------ ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ------------------------------------------------------------ ------------------------------------------------------------
    55                 2                    1801439851932090368           RID                                                          1:173:0                                                                                                                                                                                                                                                          X                                                            GRANT
    55                 2                    1801439851932090368           PAGE                                                         1:173                                                                                                                                                                                                                                                            IX                                                           GRANT
    55                 2                    309576141                     OBJECT                                                                                                                                                                                                                                                                                                                        IX                                                           GRANT */因为考虑锁问题时,需要从多个方面来探讨
    1、锁的粒度
    2、锁的模式
    3、隔离级别加索引后,在不同的隔离级别下有所不同。而且索引还分聚集索引与非聚集索引之分。
    一般而言:
    如果是非聚集索引,需要对leaf页加锁,有时候反而增加了负担;
    如果是聚集索引,是对索引加锁,与对heap表加锁差别应该不是很大。
      

  13.   


    INSERT的表默认只加行级锁,上面有人已经说了。
      

  14.   

    BFS_BusinessInfo的索引是BusinessId
    BFS_ImageStoreInfo的索引是BusinessGuid
    这两个都是非聚集索引吗?
    if (@n>0)
    begin
    delete from BFS_ImageStoreInfo
    where BusinessGuid=(
    select BusinessGuid from BFS_BusinessInfo with (nolock) 
    where BusinessId= @BusinessId )
    --1. BFS_ImageStoreInfo索引页BusinessGuid的更新锁
    --2. BFS_ImageStoreInfo数据页的排它锁
    delete from BFS_BusinessInfo
    where BusinessId=@BusinessId
    --3. BFS_BusinessInfo索引页BusinessId的更新锁
    --4. BFS_BusinessInfo数据页的排它锁
    endinsert into BFS_BusinessInfo
    --5. BFS_BusinessInfo数据页的排它锁从这个存储过程分析,可能产生死锁的地方是第3步和第5步。
    但这些应该都是行级锁。最好用Profiler跟踪一下,监控一下实际加锁过程。
      

  15.   

    不知道是不是非聚集索引,两张表建索引的语句都是下面的语句,这两个索引都不是主键。
    -- 创建表索引
    IF EXISTS (SELECT name FROM sys.indexes
                WHERE name = N'IX_BFS_BusinessInfo')
        DROP INDEX IX_BFS_BusinessInfo ON BFS_BusinessInfo ;
    GO
    CREATE INDEX IX_BFS_BusinessInfo
        ON BFS_BusinessInfo (BusinessId);
    GO
    如果我在delete那里加一个事务,insert那里加一个事务,两个数据库事务,能不能解决问题呢?
      

  16.   

    最好用Profiler跟踪一下,监控一下实际加锁过程。上面只是分析,不一定准确。也可能是别的原因造成的。
      

  17.   

    Profiler怎么跟踪加锁的过程?
    怎么用?
    怎么看profiler的日志?
      

  18.   


    http://www.sqlservercentral.com/articles/books/65797/或者用dbcc traceon(1222,-1)
    dbcc traceon(1204,-1)
    然后在errorlog里面也是可以看到的。
      

  19.   

    我不输入任何命令,当死锁发生时,我直接在errorlog里面可不可以看到死锁的消息啊?
      

  20.   

       我现在尝试把我的存储过程up_InsertBFSBusinessInfo分成两个事务来处理,
    就是在delete的时候是一个事务,insert是一个事务。
    这样可不可以解决死锁的问题,
    还是在insert那里加一个with(rowlock)可不可以减少死锁的问题。
      

  21.   

    --删除已存在的影像存储信息
    delete from BFS_ImageStoreInfo
    where BusinessGuid=(
    select BusinessGuid from BFS_BusinessInfo with (nolock)  
    where BusinessId= @BusinessId )  --删除已存在的业务信息
    delete from BFS_BusinessInfo
    where BusinessId=@BusinessId  这两个步骤,一次要删除多少数据?  
      

  22.   

    --删除已存在的影像存储信息
    delete from BFS_ImageStoreInfo
    where BusinessGuid=(
    select BusinessGuid from BFS_BusinessInfo with (nolock)   
    where BusinessId= @BusinessId )
    删除2条--删除已存在的业务信息
    delete from BFS_BusinessInfo
    where BusinessId=@BusinessId 
    删除1条
      

  23.   

    set statistics io,profile on执行下面的,找一个例子
    --删除已存在的影像存储信息
    delete from BFS_ImageStoreInfo
    where BusinessGuid=(
    select BusinessGuid from BFS_BusinessInfo with (nolock)  
    where BusinessId= @BusinessId )  --删除已存在的业务信息
    delete from BFS_BusinessInfo
    where BusinessId=@BusinessId  看看结果。
      

  24.   

    表 'BFS_ImageStoreInfo'。扫描计数 1,逻辑读取 14 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    表 'BFS_BusinessInfo'。扫描计数 1,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。(2 行受影响)(8 行受影响)
    表 'BFS_BusinessInfo'。扫描计数 1,逻辑读取 8 次,物理读取 0 次,预读 0 次,lob 逻辑读取 4 次,lob 物理读取 0 次,lob 预读 0 次。(1 行受影响)(4 行受影响)这个是执行后的消息。
    结果是
    2,1,delete from BFS_ImageStoreInfo
    where BusinessGuid=(
    select BusinessGuid from BFS_BusinessInfo with (nolock)   
    where BusinessId= 'abc1234' )  --删除已存在的业务信息,1,1,0,NULL,NULL,NULL,NULL,1,NULL,NULL,NULL,0.02657376,NULL,NULL,DELETE,0,NULL
    2,1,  |--Clustered Index Delete(OBJECT:([BFSDB].[dbo].[BFS_ImageStoreInfo].[PK__BFS_ImageStoreIn__0AD2A005]), OBJECT:([BFSDB].[dbo].[BFS_ImageStoreInfo].[IX_BFS_ImageStoreInfo])),1,2,1,Clustered Index Delete,Delete,OBJECT:([BFSDB].[dbo].[BFS_ImageStoreInfo].[PK__BFS_ImageStoreIn__0AD2A005]), OBJECT:([BFSDB].[dbo].[BFS_ImageStoreInfo].[IX_BFS_ImageStoreInfo]),NULL,1,0.02,2E-06,9,0.02657376,NULL,NULL,PLAN_ROW,0,1
    2,1,       |--Top(ROWCOUNT est 0),1,3,2,Top,Top,TOP EXPRESSION:((0)),NULL,1,0,1E-07,17,0.00657176,[BFSDB].[dbo].[BFS_ImageStoreInfo].[ImageStoreGuid],NULL,PLAN_ROW,0,1
    2,1,            |--Nested Loops(Inner Join, OUTER REFERENCES:([Expr1011])),1,4,3,Nested Loops,Inner Join,OUTER REFERENCES:([Expr1011]),NULL,1,0,4.18E-06,17,0.00657166,[BFSDB].[dbo].[BFS_ImageStoreInfo].[ImageStoreGuid],NULL,PLAN_ROW,0,1
    1,1,                 |--Assert(WHERE:(CASE WHEN [Expr1010]>(1) THEN (0) ELSE NULL END)),1,5,4,Assert,Assert,WHERE:(CASE WHEN [Expr1010]>(1) THEN (0) ELSE NULL END),NULL,1,0,1.8E-07,36,0.00328438,[Expr1011],NULL,PLAN_ROW,0,1
    1,1,                 |    |--Stream Aggregate(DEFINE:([Expr1010]=Count(*), [Expr1011]=ANY([BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid]))),1,6,5,Stream Aggregate,Aggregate,NULL,[Expr1010]=Count(*), [Expr1011]=ANY([BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid]),1,0,1.1E-06,44,0.0032842,[Expr1010], [Expr1011],NULL,PLAN_ROW,0,1
    1,1,                 |         |--Index Seek(OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[IX_BFS_BusinessInfo]), SEEK:([BFSDB].[dbo].[BFS_BusinessInfo].[BusinessId]='abc1234') ORDERED FORWARD),1,7,6,Index Seek,Index Seek,OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[IX_BFS_BusinessInfo]), SEEK:([BFSDB].[dbo].[BFS_BusinessInfo].[BusinessId]='abc1234') ORDERED FORWARD,[BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid],1,0.003125,0.0001581,47,0.0032831,[BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid],NULL,PLAN_ROW,0,1
    2,1,                 |--Index Seek(OBJECT:([BFSDB].[dbo].[BFS_ImageStoreInfo].[IX_BFS_ImageStoreInfo]), SEEK:([BFSDB].[dbo].[BFS_ImageStoreInfo].[BusinessGuid]=[Expr1011]) ORDERED FORWARD),1,12,4,Index Seek,Index Seek,OBJECT:([BFSDB].[dbo].[BFS_ImageStoreInfo].[IX_BFS_ImageStoreInfo]), SEEK:([BFSDB].[dbo].[BFS_ImageStoreInfo].[BusinessGuid]=[Expr1011]) ORDERED FORWARD,[BFSDB].[dbo].[BFS_ImageStoreInfo].[ImageStoreGuid],1,0.003125,0.0001581,17,0.0032831,[BFSDB].[dbo].[BFS_ImageStoreInfo].[ImageStoreGuid],NULL,PLAN_ROW,0,11,1,DELETE [BFS_BusinessInfo]  WHERE [BusinessId]=@1,2,1,0,NULL,NULL,NULL,NULL,1,NULL,NULL,NULL,0.0232852,NULL,NULL,DELETE,0,NULL
    1,1,  |--Clustered Index Delete(OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[PK__BFS_BusinessInfo__08EA5793]), OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[IX_BFS_BusinessInfo])),2,2,1,Clustered Index Delete,Delete,OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[PK__BFS_BusinessInfo__08EA5793]), OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[IX_BFS_BusinessInfo]),NULL,1,0.02,2E-06,9,0.0232852,NULL,NULL,PLAN_ROW,0,1
    1,1,       |--Top(ROWCOUNT est 0),2,3,2,Top,Top,TOP EXPRESSION:((0)),NULL,1,0,1E-07,47,0.0032832,[BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid],NULL,PLAN_ROW,0,1
    1,1,            |--Index Seek(OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[IX_BFS_BusinessInfo]), SEEK:([BFSDB].[dbo].[BFS_BusinessInfo].[BusinessId]=[@1]) ORDERED FORWARD),2,4,3,Index Seek,Index Seek,OBJECT:([BFSDB].[dbo].[BFS_BusinessInfo].[IX_BFS_BusinessInfo]), SEEK:([BFSDB].[dbo].[BFS_BusinessInfo].[BusinessId]=[@1]) ORDERED FORWARD,[BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid],1,0.003125,0.0001581,47,0.0032831,[BFSDB].[dbo].[BFS_BusinessInfo].[BusinessGuid],NULL,PLAN_ROW,0,1
      

  25.   

    在执行这个存储过程之前,有一个update的存储过程操作过数据库,
    这个有影响吗?
    我看应用程序的日志,这两个操作的时间间隔很短。会不会有什么影响的。
      

  26.   

    update的存储过程如下
    USE BFSDB
    IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P' AND name = 'up_UpdateBFSBusinessStatus')
    BEGIN
    DROP  Procedure  up_UpdateBFSBusinessStatus
    ENDGO/******************************************************************************
    ** File: up_UpdateBFSBusinessStatus.Sql
    ** Name: up_UpdateBFSBusinessStatus
    ** Desc: 更新业务状态
    ** Return Value:
    **
    ** Auth: 
    ** Date: 2008-04-23
    *******************************************************************************
    ** Change History
    *******************************************************************************
    ** Date: Author: Description:
    ** -------- -------- ---------------------------------------
    **    
    *******************************************************************************/
    CREATE Procedure up_UpdateBFSBusinessStatus
    (
            @BusinessId varchar(20) , -- 业务流水号
            @ProcessEndTime datetime, --处理结束时间
            @ProcessStatus int , -- 处理状态
            @Re text -- 描述)AS
    BEGIN TRANSACTION Tran_BFSupdate BFS_BusinessInfo
    set 
    ProcessEndTime=@ProcessEndTime,
    ProcessStatus=@ProcessStatus,
    Re=@Re
    where BusinessId=@BusinessId and ProcessStatus=0
    IF (@@ERROR<>0) 
    ROLLBACK TRANSACTION Tran_BFS 
    ELSE 
    COMMIT TRANSACTION Tran_BFSGO
      

  27.   

    我改了一下存储过程,

    --删除已存在的业务信息
    delete from BFS_BusinessInfo
    where BusinessId=@BusinessId 
    作为一个单独的事务来处理。这样,我这个存储过程就有三个事务。
      

  28.   

    你看看你数据库的默认隔离级别是什么,是不是读已提交,INSERT在默认隔离级别下应该不会是表锁的。
      

  29.   

    默认隔离级别怎么查看,
    我刚刚问别人,
    他们说是
    delete from BFS_BusinessInfo
    where BusinessId=@BusinessId
    这里造成的死锁。
    所以我把这个语句写成了一个事务。