当前位置: 代码迷 >> Sql Server >> 100分,继续讨论死锁的有关问题,有测试用例
  详细解决方案

100分,继续讨论死锁的有关问题,有测试用例

热度:27   发布时间:2016-04-24 09:39:42.0
100分,继续讨论死锁的问题,有测试用例
上一贴在这里:http://bbs.csdn.net/topics/390940926

当时按照讨论结果,我把不必要的索引给删除了,例子上运行没有问题了,后来上了生产数据库,发现还是有问题,还是死锁,发现好像是 PAG锁导致的。。

表中就两条记录,update 和select的是不同的记录


USE [mybase]
GO

/****** Object:  Table [dbo].[tt]    Script Date: 11/26/2014 17:25:16 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tt](
[trade_date] [char](8) NOT NULL,
[trade_time] [char](6) NOT NULL,
[key_date] [char](8) NOT NULL,
[price] [numeric](18, 3) NOT NULL,
[goods_no] [char](4) NOT NULL,
[other_price] [numeric](18, 3) NOT NULL,
 CONSTRAINT [PK_tt] PRIMARY KEY CLUSTERED 
(
[key_date] ASC,
[goods_no] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

INSERT INTO [mybase].[dbo].[tt]
           ([trade_date]
           ,[trade_time]
           ,[key_date]
           ,[price]
           ,[goods_no]
           ,[other_price])
select '0000','0000','20120101','12.35','1111','25'
union all
select '0000','0000','20140101','12.35','2222','25'
GO




1.执行事务的语句,不提交或者回滚,让事务保持进行中的状态
begin tran
UPDATE tt SET trade_time ='141125'WHERE goods_no='1111' AND key_date='20120101'

EXEC sp_lock @@spid

spid dbid ObjId IndId Type Resource Mode Status
62 5 0 0 DB                                  S GRANT
62 5 2064114494 0 TAB                                  IX GRANT
62 1 1131151075 0 TAB                                  IS GRANT
62 5 2064114494 1 PAG 1:411729                         IX GRANT
62 5 2064114494 1 KEY (47c5a781c228)                   X GRANT

2.另外开一个查询分析器窗口,执行
SELECT * FROM tt  WHERE goods_no ='2222' ORDER BY goods_no 

会死锁

这个表中就默认的主键索引,必须有的,其他的索引都没有,怎么能避免死锁呢?

------解决思路----------------------
在用到的列上加非聚集索引,还有那个select *还是能改就改
------解决思路----------------------
我拿你的数据,做了一下测试,确实会产生死锁。
原因:
1、tt表没有创建任何索引,两条数据记录存储在一个数据页上
2、执行加事务update操作,整个数据页会有意向排它锁(IX),同时这条记录(goods_no='1111' AND key_date='20120101'
)有一个行锁(X)
3、执行select操作,因为tt表没有索引,会进行全表扫描,共享锁(S)和update操作的行锁(X)产生冲突,造成死锁


解决办法:tt表创建索引
  相关解决方案