真没分了,但是又死锁了

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又没有允许脏读什么的,为什么会死锁了呢?
...全文
418 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)
《计算机操作系统》可作为计算机硬件和软件以及计算机通信专业的本科生教材,也可作为从事计算机及通信工作的相关科技人员的参考书。 目录 第一章 操作系统引论 1.1 操作系统的目标和作用 1 1.1.1 操作系统的目标 1 1.1.2 操作系统的作用 2 1.1.3 推动操作系统发展的主要动力 4 1.2 操作系统的发展过程 5 1.2.1 无操作系统的计算机系统 5 1.2.2 单道批处理系统 6 1.2.3 多道批处理系统 7 1.2.4 分时系统 9 1.2.5 实时系统 11 1.2.6 微机操作系统的发展 12 1.3 操作系统的基本特性 14 1.3.1 并发性 14 1.3.2 共享性 15 1.3.3 虚拟技术 16 1.3.4 异步性 17 1.4 操作系统的主要功能 18 1.4.1 处理机管理功能 18 1.4.2 存储器管理功能 19 1.4.3 设备管理功能 21 1.4.4 文件管理功能 21 1.4.5 操作系统与用户之间的接口 22 1.5 OS结构设计 24 1.5.1 传统的操作系统结构 24 1.5.2 客户/服务器模式 26 1.5.3 面向对象的程序设计 27 1.5.4 微内核OS结构 29 习题 33 第二章 进 程 管 理 2.1 进程的基本概念 34 2.1.1 程序的顺序执行及其特征 34 2.1.2 前趋图 35 2.1.3 程序的并发执行及其特征 36 2.1.4 进程的特征与状态 37 2.1.5 进程控制块 41 2.2 进程控制 43 2.2.1 进程的创建 43 2.2.2 进程的终止 45 2.2.3 进程的阻塞与唤醒 46 2.2.4 进程的挂起与激活 47 2.3 进程同步 47 2.3.1 进程同步的基本概念 47 2.3.2 信号量机制 50 2.3.3 信号量的应用 53 2.3.4 管程机制 55 2.4 经典进程的同步问题 58 2.4.1 生产者—消费者问题 58 2.4.2 哲学家进餐问题 61 2.4.3 读者—写者问题 63 2.5 进程通信 65 2.5.1 进程通信的类型 65 2.5.2 消息传递通信的实现方法 66 2.5.3 消息传递系统实现中的若干问题 68 2.5.4 消息缓冲队列通信机制 69 2.6 线程 71 2.6.1 线程的基本概念 72 2.6.2 线程间的同步和通信 75 2.6.3 线程的实现方式 77 2.6.4 线程的实现 78 习题 81 第三章 处理机调度与死锁 3.1 处理机调度的层次 84 3.1.1 高级调度 84 3.1.2 低级调度 86 3.1.3 中级调度 87 3.2 调度队列模型和调度准则 88 3.2.1 调度队列模型 88 3.2.2 选择调度方式和调度算法的若干准则 90 3.3 调度算法 91 3.3.1 先来先服务和短作业(进程)优先调度算法 91 3.3.2 高优先权优先调度算法 93 3.3.3 基于时间片的轮转调度算法 95 3.4 实时调度 97 3.4.1 实现实时调度的基本条件 97 3.4.2 实时调度算法的分类 99 3.4.3 常用的几种实时调度算法 100 3.5 产生死锁的原因和必要条件 103 3.5.1 产生死锁的原因 103 3.5.2 产生死锁的必要条件 105 3.5.3 处理死锁的基本方法 105 3.6 预防死锁的方法 106 3.6.1 预防死锁 106 3.6.2 系统安全状态 107 3.6.3 利用银行家算法避免死锁 108 3.7 死锁的检测与解除 111 3.7.1 死锁的检测 111 3.7.2 死锁的解除 113 习题 114 第四章 存 储 器 管 理 4.1 存储器的层次结构 116 4.1.1 多级存储器结构 116 4.1.2 主存储器与寄存器 117 4.1.3 高速缓存和磁盘缓存 117 4.2 程序的装入和链接 118 4.2.1 程序的装入 118 4.2.2 程序的链接 120 4.3 连续分配方式 121 4.3.1 单一连续分配 121 4.3.2 固定分区分配 122 4.3.3 动态分区分配 123 4.3.4 伙伴系统 126 4.3.5 哈希算法 126 4.3.6 可重定位分区分配 127 4.3.7 对换 129 4.4 基本分页存储管理方式 130 4.4.1 页面与页表 130 4.4.2 地址变换机构 131 4.4.3 两级和多级页表 133 4.5 基本分段存储管理方

22,209

社区成员

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

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