A. 深入探讨如何解决数据库中的死锁问题
具体的解决方法如下:1.再死锁发生时,我们可以通过下面的语法,查询到引起死锁的操作: use master go declare @spid int,@bl int DECLARE s_cur CURSOR FOR select 0 ,blocked from (select * from sysprocesses where blocked>0 ) a where not exists(select * from (select * from sysprocesses where blocked>0 ) b where a.blocked=spid) union select spid,blocked from sysprocesses where blocked>0 OPEN s_cur FETCH NEXT FROM s_cur INTO @spid,@bl WHILE @@FETCH_STATUS = 0 begin if @spid =0 select '引起数据库死锁的是: '+ CAST(@bl AS VARCHAR(10)) + '进程号,其执行的sql语法如下' else select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@bl AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下' DBCC INPUTBUFFER (@bl ) FETCH NEXT FROM s_cur INTO @spid,@bl end CLOSE s_cur DEALLOCATE s_cur exec sp_who2 2.然后查找程序/数据库,此t_sql语法具体在什么地方使用。3.分析已经找到的,解决问题。
B. DB2数据库发生死锁了怎么办
db2 get snapshot for locks on sample
db2 get db cfg for sample
db2 update db cfg using dlchktime 10000
-查看数据库管理器级别快照信息
db2 get snapshot for dbm
-查看数据库级别快照信息
db2 get snapshot for database on dbname
-查看应用级别快照信息
db2 get snapshot for application agentid appl-handler
注:appl-handler可以从list applicaitions的输出中得到
-查看表级别快照信息
db2 get snapshot for tables on dbname
注:需要把tables快照开关设为ON才会有作用
-查看锁快照信息
db2 get snapshot for locks on dbname
或
db2 get snapshot for locks on for application agentid appl-handler
-查看动态sql语句快照信息
db2 get snapshot for dynamic sql on dbname
db2 get monitor switches
db2 update monitor switches using lock on statement on
create event monitor mymonitor for deadlocks,statements write to file 'c:/temp'
set event monitor mymonitor state 1
db2evmon - path 'c:/temp'
--转自:http://blog.csdn.NET/rodjohnsondoctor/article/details/4323514
---
第1页:上线前的准备
第2页:维护时的注意事项
第3页:发生死锁后的对策
【IT168 技术文档】在新的数据库应用系统上线初期,由于测试不完善或不熟悉DB2的机制,常会出现锁等待死锁等现象存在于我们的应用系统中,如何捕获锁等待或死锁信息并解决锁问题,是保证平稳上线必须面对的问题。目前应用系统最常使用的DB2数据库版本有多个,有8.1,8.2,9.1还有新推出的9.5,对于不同版本的DB2数据库提供的解决办法不尽相同,下面对于上述问题的解决作了一个简单说明,希望对大家有用。
首先在上线前有几件跟锁相关的事情需要开发设计人员一定要做好
1. 相关参数的更改
注册表变量参数:
DB2_EVALUNCOMMITTED=on 当启用此变量时,在可能的情况下,它将进行表或索引访问扫描以延迟或避免行锁定,直到知道数据记录满足谓词求值为止。
DB2_SKIPDELETED=on 当启用此变量时,在可能的情况下,它允许使用无条件地跳过已删除的键或跳过已删除的行。
DB2_SKIPINSERTED=on 当启用此变量时,在可能的情况下,它允许跳过未落实的已插入行,就好像从未插入这些行一样。
数据库参数:
LOCKLIST 锁定列表的内存量,当此参数设置为 AUTOMATIC 时,就启用了自调整功能。这允许内存调整器根据工作负载需求变化动态地调整此参数控制的内存区大小。如果不是自动,需要设置相对大一些;DB2默认是行锁,每个行锁大约占64或128个字节(64位数据库),计算锁定列表内存的大小公式是: ( 每个应用程序的平均锁定数目的估计值 * 每个锁定所需的字节数(128或64) * maxappls(或者max_coordagents) /4096 ) * 120%,这里只是建议公式,实际情况还要视操作系统实际的内存量来定。
MAXLOCKS 升级前锁定列表的最大百分比,默认是22%(windows)或10%(unix),可以根据要求自行改动,计算公式是 2 * 100 / maxappls
DLCHKTIME 死锁检测时间间隔,默认是10000毫秒(10秒),可以根据要求自行改动,也可不动。增大此参数以降低检查死锁的频率,因此增加应用程序必须等待消除死锁的时间。 减小此参数会增大检查死锁的频率,从而减少应用程序必须等待死锁解决的时间,但是会增加数据库管理器检查死锁所花的时间。
LOCKTIMEOUT 锁等待时间,默认是 -1,也就是永远等待,请改成固定的值,在事务处理(OLTP)环境中,可以使用 30 秒的初始启动值。在一个只查询的环境中,您可以从一个较高的值开始。
LOGFILSIZ 日志文件大小,此参数定义每个主日志文件和辅助日志文件的大小。如果数据库要运行大量更新、删除或插入事务,而这将导致日志文件很快变满,则应增大日志文件,了解您的并发应用程序的日志记录需求,来确定一个不会分配过量而浪费空间的日志文件大小。
LOGPRIMARY 主日志文件数,了解您的并发应用程序的日志记录需求,适当增大日志文件数。
注意: 在更新参数时,需要注意有些参数在更改后需要重新启动数据库DB2实例才可以生效;有些参数需要断开当前所有的应用程序,重新链接才能生效;有些参数可以立即生效,使用者请参考相关文档,注意参数生效特性。
2. 应用程序设计
-程序尽量短小精悍
-程序尽量晚地访问关键资源
-程序尽可能快地提交工作
-程序尽可能快地关闭游标
-建立合适索引
3. 性能测试
要根据将来实际的并发用户数和数据量进行测试
上线之后维护时我们要做的几件事情
1. 做好定期维护
通过使用如下命令进行维护:
-reorg表和索引定期重组
-runstats表和索引的统计信息定期更新
-rebind 程序包定期重新编译
C. DB2 死锁怎么测试 具体的测试方法是什么
你要模拟一个 DB2 的死锁?
那么首先, 先创建一个测试表
CREATE TABLE test_main (
id INT NOT NULL,
value VARCHAR(10),
PRIMARY KEY(id)
);
和测试数据...
开2个 DB2 的命令行窗口
会话1:
db2 => select * from test_main@
ID VALUE
----------- ----------
1 ONE
2 TWO
5 Five-5
3 THREE-5
4 条记录已选择。
db2 => UPDATE test_main SET value='Two-5' WHERE id=2@
DB20000I SQL 命令成功完成。
会话2:
db2 => UPDATE test_main SET value='THREE' WHERE id=3@
DB20000I SQL 命令成功完成。
会话1:
db2 => UPDATE test_main SET value='THREE-55' WHERE id=3@
由于 id=3 的行,已经被会话2修改,并锁定,因此会话1当前进入等待状态。
会话2:
db2 => UPDATE test_main SET value='Two-2' WHERE id=2@
由于 id=2 的行,已经被会话1修改,并锁定,因此会话2当前进入等待状态。
等待一段时间后
DB21034E 该命令被当作 SQL 语句来处理,因为它是无效的“命令行处理器”命令。在
SQL 处理期间,它返回:
SQL0911N 因为死锁或超时,所以当前事务已回滚。原因码为 "2"。 SQLSTATE=40001
db2 =>
会话1
DB20000I SQL 命令成功完成。
db2 =>
db2 => select * from test_main@
ID VALUE
----------- ----------
1 ONE
2 Two-5
5 Five-5
3 THREE-55
4 条记录已选择。
会话2:
db2 => select * from test_main@
ID VALUE
----------- ----------
1 ONE
2 TWO
5 Five-5
3 THREE-5
4 条记录已选择。
显示会话二的更新已丢失。
D. 数据库查询发生死锁
导致
死锁
的主要原因是
SQL语句
里有for
update
导致。比如当你访问这个表时候
有人使用了for
update进行
数据修改
,那在你那里调试也好执行也好
都会导致无法返回结果
一直卡在那里。
E. 如何检测oracle数据库死锁
从v$locked_object中查询select
username,lockwait,status,machine,program
from
v$session
where
sid
in
(select
session_id
from
v$locked_object)
F. 如何查mysql死锁进程
查询死锁进程
采用如下存储过程来查询数据中当前造成死锁的进程。
drop procere sp_who_lock
go
CREATE procere sp_who_lock
as
begin
declare @spid int
declare @blk int
declare @count int
declare @index int
declare @lock tinyint
set @lock=0
create table #temp_who_lock
(
id int identity(1,1),
spid int,
blk int
)
if @@error<>0 return @@error
insert into #temp_who_lock(spid,blk)
select 0 ,blocked
from (select * from master..sysprocesses where blocked>0)a
where not exists(select * from master..sysprocesses where a.blocked =spid and blocked>0)
union select spid,blocked from master..sysprocesses where blocked>0
if @@error<>0 return @@error
select @count=count(*),@index=1 from #temp_who_lock
if @@error<>0 return @@error
if @count=0
begin
select '没有阻塞和死锁信息'
return 0
end
while @index<<A href="mailto:=@count">=@count
begin
if exists(select 1 from #temp_who_lock a where id>@index and exists(select 1 from #temp_who_lock where id<<A href="mailto:=@index">=@index and a.blk=spid))
begin
set @lock=1
select @spid=spid,@blk=blk from #temp_who_lock where id=@index
select '引起数据库死锁的是: '+ CAST(@spid AS VARCHAR(10)) + '进程号,其执行的SQL语法如下'
select @spid, @blk
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
end
set @index=@index+1
end
if @lock=0
begin
set @index=1
while @index<<A href="mailto:=@count">=@count
begin
select @spid=spid,@blk=blk from #temp_who_lock where id=@index
if @spid=0
select '引起阻塞的是:'+cast(@blk as varchar(10))+ '进程号,其执行的SQL语法如下'
else
select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))+ '被' + '进程号SPID:'+ CAST(@blk AS VARCHAR(10)) +'阻塞,其当前进程执行的SQL语法如下'
dbcc inputbuffer(@spid)
dbcc inputbuffer(@blk)
set @index=@index+1
end
end
drop table #temp_who_lock
return 0
end
GO
--执行该存储过程
exec sp_who_lock
补充:
一、产生死锁的原因
在SQL Server中,阻塞更多的是产生于实现并发之间的隔离性。为了使得并发连接所做的操作之间的影响到达某一期望值而对资源人为的进行加锁(锁本质其实可以看作是一个标志位)。当一个连接对特定的资源进行操作时,另一个连接同时对同样的资源进行操作就会被阻塞,阻塞是死锁产生的必要条件。
二、如何避免死锁
1.使用事务时,尽量缩短事务的逻辑处理过程,及早提交或回滚事务;
2.设置死锁超时参数为合理范围,如:3分钟-10分种;超过时间,自动放弃本次操作,避免进程悬挂;
3.优化程序,检查并避免死锁现象出现;
4.对所有的脚本和SP都要仔细测试,在正是版本之前;
5.所有的SP都要有错误处理(通过@error);
6.一般不要修改SQL SERVER事务的默认级别。不推荐强行加锁。
三、处理死锁
1、最简单的处理死锁的方法就是重启服务。
2、根据指定的死锁进程ID进行处理
根据第二步查询到的死锁进行,大致分析造成死锁的原因,并通过如下语句释放该死锁进程
kill pid --pid为查询出来的死锁进程号
3、通过存储过程杀掉某个库下面的所有死锁进程和锁
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_killspid]') and OBJECTPROPERTY(id, N'IsProcere') = 1)
drop procere [dbo].[sp_killspid]
GO
create proc sp_killspid
@dbname varchar(200) --要关闭进程的数据库名
as
declare @sql nvarchar(500)
declare @spid nvarchar(20)
declare #tb cursor for
select spid=cast(spid as varchar(20)) from master..sysprocesses where dbid=db_id(@dbname)
open #tb
fetch next from #tb into @spid
while @@fetch_status=0
begin
exec('kill '+@spid)
fetch next from #tb into @spid
end
close #tb
deallocate #tb
go
--使用方法,“db_name”为处理的数据库名称
exec sp_killspid 'db_name'
G. SQL数据库总是假死或死锁。
建议:
1、使用事件探查器,跟踪一下SQL在死锁之前执行了哪些SQL语句
2、多数死锁是因为程序没有经过严格的测试造成的
3、少部分原因是因为触发器嵌套造成的,SQL有内部机制,当嵌套到一定的层级,就自动终止掉相关的进程
愿早日解决问题
H. 数据库:如何使一张表产生死锁现象从而无法访问
如果是sqlserver的话,给出下面示例
SELECT
*
FROM
table
WITH
(HOLDLOCK)
其他事务可以读取表,但不能更新删除
SELECT
*
FROM
table
WITH
(TABLOCKX)
其他事务不能读取表,更新和删除
如果是oracle的话,lz可以使用for
update用法
select
*
from
TTable1
for
update
锁定表的所有行,只能读不能写
有问题再追问。
I. 怎样通过程序判断数据库是否死锁
一般采用超时法或事务等待图法: (1)超时法 如果一个事务的等待时间超过规定时间,就认为发生了死锁。这个实现简单,但不足也很明显。 (2)事务等待图法 事务等待图是一个有向图G=(T, U),