真没分了,但是又死锁了

shaoming01 2014-07-15 08:01:19
A线程,没开事务,同一个连接里面
语句1
Select *
FROM TableA
LEFT JOIN TableB
语句2(死锁)
Select Count(*)
FROM TableA
LEFT JOIN TableB

B线程
开事务
Insert into TableA
Insert Into TableB (死锁)
我没搞懂,我insert完了以后才提交事务的,
select又没有允许脏读什么的,为什么会死锁了呢?
...全文
517 35 打赏 收藏 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
Tiger_Zhao 2014-07-17
  • 打赏
  • 举报
回复
1.既然 COUNT 视图和 COUNT 单表结果一样,就没必要用视图。
2.SELECT TOP 50 ...
shaoming01 2014-07-17
  • 打赏
  • 举报
回复
引用 33 楼 Tiger_Zhao 的回复:
[quote=引用 15 楼 shaoming01 的回复:] 下面这个是把语句拉出来实测的 上面的语句先执行,再执行select就死锁了
SELECT Count(*) 没有条件,就是取全表记录数!
引用 29 楼 shaoming01 的回复:
其实我的2张表保存的是同一张单据,但是单据中某些字段很大,为了提交效率单独做了1张表来存放经常需要更新的字段
既然两表是一对一的,没必要JOIN 后在计数,随便对一个计数就可以了吧? sysindexes.rowcnt 有记录数,拿主键的名称取查好了,用不着 COUNT(*),也就不会有锁了。 又:已经有了 SELECT * ,再来一个 SELECT Count(*),这样真不觉得奇怪吗?[/quote] 1,用Join再Count是因为实际上Join的写法在视图里面,外面是没办法的 2,前面用select *其实只是一种写法,实际是分页后取某一页的值,可能只取50条 ,所以后面需要用select Count(*)
Tiger_Zhao 2014-07-17
  • 打赏
  • 举报
回复
引用 15 楼 shaoming01 的回复:
下面这个是把语句拉出来实测的 上面的语句先执行,再执行select就死锁了
SELECT Count(*) 没有条件,就是取全表记录数!
引用 29 楼 shaoming01 的回复:
其实我的2张表保存的是同一张单据,但是单据中某些字段很大,为了提交效率单独做了1张表来存放经常需要更新的字段
既然两表是一对一的,没必要JOIN 后在计数,随便对一个计数就可以了吧? sysindexes.rowcnt 有记录数,拿主键的名称取查好了,用不着 COUNT(*),也就不会有锁了。 又:已经有了 SELECT * ,再来一个 SELECT Count(*),这样真不觉得奇怪吗?
shaoming01 2014-07-16
  • 打赏
  • 举报
回复
我一直以为insert是不锁表的,但事实好像不是这样的
shaoming01 2014-07-16
  • 打赏
  • 举报
回复
请看一下我15楼发的精简结果.
Andy-W 2014-07-16
  • 打赏
  • 举报
回复
select Count(*) ... from a inner join b 没where条件,目的是干啥? 如果這樣,與insert a ....insert b 事务,不死锁都难。 如果不降低事务隔离级别,就要提升select 部分的查询效率和减低insert事务部分的时间。 先检查表有没有索引,有没有主键,外键。外键上记得要创建索引,这样可以减少类似死锁的发生。
Andy-W 2014-07-16
  • 打赏
  • 举报
回复
为什么要waitfor delay? 像楼主这样的情况,我看像是表数据量大,或频繁执行select count() 语句,导致与insert事务出现死锁。 select count(..) from部分, 可以先通过降低事务隔离级别来避免这样的死锁。 如在select count() from 部分的回话中设置: set transaction isolation level read uncommitted 还可以检查select count 部分的性能,是否可以建立索引來优化。
shaoming01 2014-07-16
  • 打赏
  • 举报
回复
下面这个是把语句拉出来实测的
上面的语句先执行,再执行select就死锁了

shaoming01 2014-07-16
  • 打赏
  • 举报
回复
有关联,通过聚焦索引Id字段关键的. Id是GUID类型
發糞塗牆 2014-07-16
  • 打赏
  • 举报
回复
A/B两表是外键关联吗?
shaoming01 2014-07-16
  • 打赏
  • 举报
回复
2线程必须同时执行才会死锁.
發糞塗牆 2014-07-16
  • 打赏
  • 举报
回复
只执行这个就死锁还是两个线程一起执行就死锁? Select * FROM TableA LEFT JOIN TableB Select Count(*) FROM TableA LEFT JOIN TableB
极品老土豆 2014-07-16
  • 打赏
  • 举报
回复

/*
--可以查一下该page里什么数据
--不过这个死锁极好想想
--你一条语句拥有A表的共享锁,然后,请求B表的共享锁
--你另一条语句,拥有B表的排它锁,请求A表的排它锁。
--如下建议,修改隔离模式。
--uncommit read 可以解决
*/
先生鲁 2014-07-16
  • 打赏
  • 举报
回复
楼主表达不清楚呢.要看下具体环境才知道原因.selecyt shi
Andy-W 2014-07-16
  • 打赏
  • 举报
回复
不过,这样的结果会出现脏读,也就是其他进程未commit的tran,你select ...(nolock)都可以看到未提交的数据。
shaoming01 2014-07-16
  • 打赏
  • 举报
回复
其实我的业务很简单的, 就是一个包含2张表的视图, 做新增数据的时候,这2张表的数据需要在同一个事务里insert 查询这个视图的时候也要一起查出来,现在就遇上这样的问题了. 只要先insert事务,再查询这个视图,就会死锁. 没想到这么简单的业务会带来这么麻烦的问题,请问针对这样的业务一般用什么方案呢? 其实我的2张表保存的是同一张单据,但是单据中某些字段很大,为了提交效率单独做了1张表来存放经常需要更新的字段
Andy-W 2014-07-16
  • 打赏
  • 举报
回复
引用 25 楼 shaoming01 的回复:
引用这句:"由于在lock models中,IX锁和S锁是互斥" 有没有办法让Ix锁和S锁不互斥,会不会带来什么后果?
这是锁的规则。你想不互斥,可以在Select部分加nolock,如 select count(1) from tableA with(nolock) inner join tableB with(nolock) on ... 不过,这样的结果会出现脏读,也就是其他进程未提供的tran,你select ...(nolock)都可以看到未提交的数据。
發糞塗牆 2014-07-16
  • 打赏
  • 举报
回复
锁机制不是为了为难你,而是为了保护你的数据
發糞塗牆 2014-07-16
  • 打赏
  • 举报
回复
引用 25 楼 shaoming01 的回复:
引用这句:"由于在lock models中,IX锁和S锁是互斥" 有没有办法让Ix锁和S锁不互斥,会不会带来什么后果?
快照隔离,但是不到实在没有其他办法前不要轻易使用,每种技术都有优缺点。重点应该是优化你的写法和逻辑
shaoming01 2014-07-16
  • 打赏
  • 举报
回复
引用这句:"由于在lock models中,IX锁和S锁是互斥" 有没有办法让Ix锁和S锁不互斥,会不会带来什么后果?
加载更多回复(15)

22,298

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server 疑难问题
社区管理员
  • 疑难问题社区
  • 尘觉
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧