怎么调试一段程序会出现卡死状况

如何调试一段程序会出现卡死状况?
一段程序,主要实现订单的新增与保存,中间有一个判断是新增还是追加,用的是一个计算项,没有保存。

其他就是普通的表头表体保存,对应的是两张表。审核的时候会生成一个子表用量,也是对应两张表。(有一张相同,另一张表不同。)

现在的故障现象是:在本机运行没有问题,在客户端运行有时会出现卡死现象,就是点击保存后很久没有反应,这个时候也操作不了软件,需要停止SQL再运行SQL才能重新运行,单据也没有保存到,但是同样的操作再做又可以保存。

用过的锁表语法如下:update 表名 set id = id where 1=0;
也用过如下锁表语法:

nn:
update 表名
set id = id
where id in(select top 1 isnull(id,'') from 表名)
using sqlca;
if sqlca.sqlcode = 0 then 
else
goto nn
end if

保存和审核的语法都是直接写SQL语句的。不是调用PB的update。

请教高手,如果是你如何找这个BUG?

我考虑的问题的可能性有:1、网络不稳定;保存的时候出现丢包现象;但是我觉得不稳定不至于这么频繁;
2、字段不符合规范,如字段过长,特殊字符,字段不匹配,但是同样的操作又可以保存,十分奇怪;
3、多用户冲突,但是操作的用户其实也不多,一般也就3个左右。
4、PB自身的BUG,而我恰恰猜中这个地雷了。不知道这种可能性有多大??
5、。。。。。。。。。。。

想不出来一个好的调试办法,请高手指点一下。








------解决方案--------------------
deadlocks(死锁)

所谓死锁<DeadLock>: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程. 

由于资源占用是互斥的,当某个进程提出申请资源后,使得有关进程在无外力协助下,永远分配不到必需的资源而无法继续运行,这就产生了一种特殊现象死锁。

一种情形,此时执行程序中两个或多个线程发生永久堵塞(等待),每个线程都在等待被其他线程占用并堵塞了的资源。例如,如果线程A锁住了记录1并等待记录2,而线程B锁住了记录2并等待记录1,这样两个线程就发生了死锁现象。

计算机系统中,如果系统的资源分配策略不当,更常见的可能是程序员写的程序有错误等,则会导致进程因竞争资源不当而产生死锁的现象。

产生死锁的原因主要是:

(1) 因为系统资源不足。

(2) 进程运行推进的顺序不合适。

(3) 资源分配不当等。

如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁

产生死锁的四个必要条件:

(1) 互斥条件:一个资源每次只能被一个进程使用。 

(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。 

(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之 一不满足,就不会发生死锁。

死锁的解决:预防和解除

1。死锁的预防:1)一次封锁法:就是要求每个事务必须一次将所有要使用的数据全部加锁,否则就不能继续执行。但是出现这样的问题:因为一次给全部数据加锁,从而降低系统的并发度,同时数据库中数据是不断变化的,原来不要求封锁的数据在执行过程中可能会变成封锁对象。2)顺序封锁法,预先对数据对象规定一个封锁顺序,所有事务都按这个顺序实行封锁,问题:数据库中数据对象多,且不断的变化,维护困难,成本高;事务的封锁请求可以随着事务的执行而动态的决定。

2。检测死锁

企业管理器->可以在[管理]->[当前活动] 里看到阻塞信息(有时SQL Server企业管理器会因为锁太多而没有响应). 

设定跟踪1204:

USE MASTER
DBCC TRACEON (1204,-1)

显示当前启用的所有跟踪标记的状态:

DBCC TRACESTATUS(-1)

取消跟踪1204:

DBCC TRACEOFF (1204,-1)

在设定跟踪1204后,会在数据库的日志文件里显示SQL Server数据库死锁时一些信息。但那些信息很难看懂,需要对照SQL Server联机丛书仔细来看。根据PAG锁要找到相关数据库表的方法:

DBCC TRACEON (3604)
DBCC PAGE (db_id,file_id,page_no)
DBCC TRACEOFF (3604) 

可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。

写了一个系统存储过程sp_who_lock.sql。代码如下:

 



if exists (select * from dbo.sysobjects
where id = object_id(N'[dbo].[sp_who_lock]')
and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[sp_who_lock]
GO
/**//********************************************************
// 说明 : 查看数据库里阻塞和死锁情况
********************************************************/
use master
go
create procedure sp_who_lock
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntry int,
@intRowcount int,
@intCountProperties int,
@intCounter int
create table #tmp_lock_who (
id int identity(1,1),
spid smallint,
bl smallint)
IF @@ERROR<>0 RETURN @@ERROR
insert into #tmp_lock_who(spid,bl) 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
IF @@ERROR<>0 RETURN @@ERROR
-- 找到临时表的记录数
select @intCountProperties = Count(*),@intCounter = 1
from #tmp_lock_who
IF @@ERROR<>0 RETURN @@ERROR
if @intCountProperties=0
select '现在没有阻塞和死锁信息' as message
-- 循环开始
while @intCounter <= @intCountProperties