left join 都没有连接的条件么???

解决方案 »

  1.   

    这就是个意思,不是真没有条件的,
    真实条件是
    TableA.Id=TableB.Id
      

  2.   

    问题是B线程纯粹做的是insert为什么会锁表呢?
      

  3.   

    而且楼主这种情况应该是引起了阻塞,并非死锁,如果是05(包含)以上版本的话用try catch捕获下异常信息看看。
      

  4.   

    只执行这个就死锁还是两个线程一起执行就死锁?
    Select * 
    FROM TableA
    LEFT JOIN TableBSelect Count(*) 
    FROM TableA
    LEFT JOIN TableB
      

  5.   

    有关联,通过聚焦索引Id字段关键的.
    Id是GUID类型
      

  6.   

    下面这个是把语句拉出来实测的
    上面的语句先执行,再执行select就死锁了
      

  7.   

    为什么要waitfor delay?
    像楼主这样的情况,我看像是表数据量大,或频繁执行select count() 语句,导致与insert事务出现死锁。select count(..) from部分, 可以先通过降低事务隔离级别来避免这样的死锁。如在select count() from 部分的回话中设置:
    set transaction isolation level read uncommitted 还可以检查select count 部分的性能,是否可以建立索引來优化。
      

  8.   

    select Count(*) ... from a inner join b 没where条件,目的是干啥?
    如果這樣,與insert a ....insert b 事务,不死锁都难。如果不降低事务隔离级别,就要提升select 部分的查询效率和减低insert事务部分的时间。先检查表有没有索引,有没有主键,外键。外键上记得要创建索引,这样可以减少类似死锁的发生。
      

  9.   

    我一直以为insert是不锁表的,但事实好像不是这样的
      

  10.   

    1、insert也会锁
    2、锁表和锁是不衡等的,不是每次都锁表。
    3、insert锁表的顺序是先在表上加IX 在页上加IX ,在ROW上加X
    4、SELECT COUNT会在所有页上加S锁,而你join会导致两个表都加S锁,锁的范围更广。
    5、当线程Aselect 的时候,在两个表上加了S锁,线程B此时第一次INSERT,加IX锁,这个没问题。但是接下来线程A又一次SELECT ,由于S锁在默认隔离级别下select完就会释放,所以第二次select时再次加S锁,但是由于B对TableA加了IX锁,所以A线程不能对TableA加S锁。另外线程B在第一次insert的时候由于A/B两表有外键,所以B的对应数据上也会加IX锁,第二次insert 到B的时候IX和前面INSERT中B表上的IX不兼容,又需要等待,导致A、B两个线程都在等待。最终死锁。
    这个好像有点乱。比较不好理解。解决建议:
    1、在A/B两表(不是线程)上的外键关联列,如果没有索引的话,加上一个非聚集索引
    2、在A/B两表上,找出最窄的非NULL列,建一个索引。
      

  11.   


    对1楼的第2个死锁图进行简要说明:
    ===================================1.根据图,先对他们作几个标记:
    --------------------------
    右边的椭圆:     进程103
    左边的椭圆:     进程75
    中间位置上边框: 资源37467
    中间位置下边框: 资源36940
    2.分析图,同一时间内存在下面两种情况:
    ----------------------------------- a: 进程103对资源37467,持有1个意向独占锁(IX)    ,与此同时,进程75对资源37467,请求1个共享锁(S)
    b: 进程75对资源36940,持有1个共享锁(S)          ,与此同时,进程103对资源36940,请求1个意向独占锁(IX)3.使用二维表描述两个资源的状态:
    -----------------------------------------
    资源                  持有               请求
    -----------------------------------------
    资源37467     进程103(IX)    进程75(S)
    资源36940     进程75(S)       进程103(IX)4.由于在lock models中,IX锁和S锁是互斥,不兼容。简单说就是一个资源,存在了IX锁,不能再存在一个S锁,反之亦然;
    在这里场景中,它们两个进程同时对两个资源各存在‘持有’和‘请求’的状态,
    由于两个进程不会主动释放资源,它们会进入一个持有与请求的僵局。5.sql server系统(boss),发现这样一个僵局,没办法,为了维持资源的可利用,对对立的双方进行仲裁,宣判其中一个进程作为牺牲品,另一进程继续作业。
      

  12.   

    引用这句:"由于在lock models中,IX锁和S锁是互斥"有没有办法让Ix锁和S锁不互斥,会不会带来什么后果?
      

  13.   


    这是锁的规则。你想不互斥,可以在Select部分加nolock,如select count(1) from tableA with(nolock) inner join tableB with(nolock) on ...不过,这样的结果会出现脏读,也就是其他进程未提供的tran,你select  ...(nolock)都可以看到未提交的数据。
      

  14.   

    其实我的业务很简单的,
    就是一个包含2张表的视图,做新增数据的时候,这2张表的数据需要在同一个事务里insert
    查询这个视图的时候也要一起查出来,现在就遇上这样的问题了.
    只要先insert事务,再查询这个视图,就会死锁.
    没想到这么简单的业务会带来这么麻烦的问题,请问针对这样的业务一般用什么方案呢?其实我的2张表保存的是同一张单据,但是单据中某些字段很大,为了提交效率单独做了1张表来存放经常需要更新的字段
      

  15.   

    不过,这样的结果会出现脏读,也就是其他进程未commit的tran,你select  ...(nolock)都可以看到未提交的数据。
      

  16.   

    楼主表达不清楚呢.要看下具体环境才知道原因.selecyt shi
      

  17.   


    /*
    --可以查一下该page里什么数据
    --不过这个死锁极好想想
    --你一条语句拥有A表的共享锁,然后,请求B表的共享锁
    --你另一条语句,拥有B表的排它锁,请求A表的排它锁。
    --如下建议,修改隔离模式。
    --uncommit read 可以解决
    */
      

  18.   

    SELECT Count(*) 没有条件,就是取全表记录数!
    既然两表是一对一的,没必要JOIN 后在计数,随便对一个计数就可以了吧?
    sysindexes.rowcnt 有记录数,拿主键的名称取查好了,用不着 COUNT(*),也就不会有锁了。又:已经有了 SELECT * ,再来一个 SELECT Count(*),这样真不觉得奇怪吗?
      

  19.   

    SELECT Count(*) 没有条件,就是取全表记录数!
    既然两表是一对一的,没必要JOIN 后在计数,随便对一个计数就可以了吧?
    sysindexes.rowcnt 有记录数,拿主键的名称取查好了,用不着 COUNT(*),也就不会有锁了。又:已经有了 SELECT * ,再来一个 SELECT Count(*),这样真不觉得奇怪吗?1,用Join再Count是因为实际上Join的写法在视图里面,外面是没办法的
    2,前面用select *其实只是一种写法,实际是分页后取某一页的值,可能只取50条 ,所以后面需要用select Count(*)
      

  20.   

    1.既然 COUNT 视图和 COUNT 单表结果一样,就没必要用视图。
    2.SELECT TOP 50 ...