赞
踩
工作些年,常听见的一名话是
“死锁是程序问题,不能通过优化数据库来解决死锁,必须要改写程序,做好事务与访问顺序方面的控制”
如果产生死锁的业务模块频繁访问大量堆表,通过数据库优化是在一定的概率下可以解决死锁问题的,实际工作中,大概有百分四十的概率可以通过优化索引解决死锁问题。
死锁概念产生原理在csdn上的很多。
在这里举个通过索引优化解决死锁问题的简单栗子,证明我来过...
窗口1:创建测试表
- USE [test]
- GO
- /****** Object: Table [dbo].[t2] Script Date: 2018/5/29 18:52:46 ******/
- SET ANSI_NULLS ON
- GO
- SET QUOTED_IDENTIFIER ON
- GO
- CREATE TABLE [dbo].[t2](
- [f1] [int] NULL,
- [f2] [int] NULL
- ) ON [PRIMARY]
-
- GO
- /****** Object: Index [i2] Script Date: 2018/5/29 18:52:46 ******/
- CREATE CLUSTERED INDEX [i2] ON [dbo].[t2]
- (
- [f1] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- GO
- INSERT [dbo].[t2] ([f1], [f2]) VALUES (1, 1)
- GO
- INSERT [dbo].[t2] ([f1], [f2]) VALUES (1, 2)
- GO
- INSERT [dbo].[t2] ([f1], [f2]) VALUES (2, 1)
- GO
- INSERT [dbo].[t2] ([f1], [f2]) VALUES (2, 2)
- GO
窗口2:查询1
- --execute 1
- begin tran
- --execute 1
- update t2 set f1=f1 where f1=1 and f2=1
- --execute 3
- select * from t2 where f1=2 and f2=2
- --execute 5
- rollback
窗口2:查询2
- --execute 2
- begin tran
- --execute 2
- update t2 set f1=f1 where f1=2 and f2=1
- --execute 4
- select * from t2 where f1=1 and f2=2
- --execute 6
- rollback
按照注释execute 1、2、3、4、5、6依次选中运行
执行到第四步,sql server自动检测到死锁并kill 之
至此窗口2,3运行rollback释放锁。
解决办法
通过添加正确索引来以免本例子中的update过度锁数据。
- CREATE NONCLUSTERED INDEX [i3] ON [dbo].[t2]
- (
- [f1] ASC,
- [f2] ASC
- )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
- GO
按照注释execute 1、2、3、4、5、6依次选中运行
执行到第四步,不会死锁,正常返回结果。
最后execute 5、6
Rollback
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。