上一贴在这里: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表创建索引