‘壹’ sql 进程死锁
首先,需要把你的AutoCommit=TRUE,然后,这是一个编程习惯问题,在pb中,对于数据窗口的操作,首先设置数据窗口的提交方式,我一直
采用 key columns,use
update,然后记得在每次连接完成后,记得及时释放,譬如,在retrieve完成后,记得及时利用resetupdate()清除数据状态,然后,
再每次数据库更新,也就是update()后,记得利用
ll_num1=.update()
if ll_num=1 then
commit;
dw_free.resetupdate( )
else
rollback;
messagebox("提示!","数据保存失败! ")
end if
以上说法我不赞同:
1、首先AutoCommit=TRUE,以后执行delete,update,insert语句都相当执行了commit,如果是把几个SQL语句当作是一个完整的事务,要不整
体成功提交,要不rollback,这就写就不会得到正确的结果。
2、其次key columns,use update,要具体情况具体使用,这种形式的并发性最差,适合对数据的并发性要求不高的场合。
3、再次程序的死锁原因是多方面的,上述两个方面只是其中的原因罢了,具体情况具体分析,例如数据尽快提交、建立合理的索引、合理的SQ
L语句、避免交叉事务、对于数据量庞大的表,应及时转移到历史库,我想可以很大程度上避免死锁。
以上愚见,欢迎拍砖。
在MSSQL控制台中,管理-当前活动-锁/进程ID看看是那几个进程在死锁,然后在进程信息中将这些死锁的进程杀死/
对查询进行优化
也建议检查:外键建立索引,如果上索引,再调试下网络
对外键建索引可以缓解这个问题。
如在商品字典和销售明细表中,销售明细表中商品编号是外键,如果在销售明细表的商品编号上没有索引,update商品字典会造成销售明细表
整表锁表。
解决Sybase数据库死锁的方法
人民银行吉林市中心支行科技处 刘志明
在联机事务处理(OLTP)的数据库应用系统中,多用户、多任务的并发性是系统最重要的技术指标之一。为了提高并发性,目前大部分RDBMS都采
用加锁技术。然而由于现实环境的复杂性,使用加锁技术又不可避免地产生了死锁问题。因此如何合理有效地使用加锁技术,最小化死锁是开
发联机事务处理系统的关键。
死锁产生的原因
在联机事务处理系统中,造成死机主要有两方面原因。一方面,由于多用户、多任务的并发性和事务的完整性要求,当多个事务处理对多个资
源同时访问时,若双方已锁定一部分资源但也都需要对方已锁定的资源时,无法在有限的时间内完全获得所需的资源,就会处于无限的等待状
态,从而造成其对资源需求的死锁。
另一方面,数据库本身加锁机制的实现方法不同,各数据库系统也会产生其特殊的死锁情况。如在Sybase SQL Server 11中,最小锁为2K一页
的加锁方法,而非行级锁。如果某张表的记录数少且记录的长度较短(即记录密度高,如应用系统中的系统配置表或系统参数表就属于此类表)
,被访问的频率高,就容易在该页上产生死锁。
几种死锁情况及解决方法
清算应用系统中,容易发生死锁的几种情况如下:
● 不同的存储过程、触发器、动态SQL语句段按照不同的顺序同时访问多张表;
● 在交换期间添加记录频繁的表,但在该表上使用了非群集索引(non-clustered);
● 表中的记录少,且单条记录较短,被访问的频率较高;
● 整张表被访问的频率高(如代码对照表的查询等)。
以上死锁情况的对应处理方法如下:
● 在系统实现时应规定所有存储过程、触发器、动态SQL语句段中,对多张表的操作总是使用同一顺序。如:有两个存储过程proc1、proc2,
都需要访问三张表zltab、z2tab和z3tab,如果proc1按照zltab、z2tab和z3tab的顺序进行访问,那么,proc2也应该按照以上顺序访问这三张
表。
● 对在交换期间添加记录频繁的表,使用群集索引(clustered),以减少多个用户添加记录到该表的最后一页上,在表尾产生热点,造成死锁
。这类表多为往来账的流水表,其特点是在交换期间需要在表尾追加大量的记录,并且对已添加的记录不做或较少做删除操作。
● 对单张表中记录数不太多,且在交换期间select或updata较频繁的表可使用设置每页最大行的办法,减少数据在表中存放的密度,模拟行级
锁,减少在该表上死锁情况的发生。这类表多为信息繁杂且记录条数少的表。
如:系统配置表或系统参数表。在定义该表时添加如下语句:
with max_rows_per_page=1
● 在存储过程、触发器、动态SQL语句段中,若对某些整张表select操作较频繁,则可能在该表上与其他访问该表的用户产生死锁。对于检查
账号是否存在,但被检查的字段在检查期间不会被更新等非关键语句,可以采用在select命令中使用at isolation read uncommitted子句的方
法解决。该方法实际上降低了select语句对整张表的锁级别,提高了其他用户对该表操作的并发性。在系统高负荷运行时,该方法的效果尤为
显着。
例如:
select*from titles at isolation read uncommitted
● 对流水号一类的顺序数生成器字段,可以先执行updata流水号字段+1,然后再执行select获取流水号的方法进行操作。
小结
笔者对同城清算系统进行压力测试时,分别对采用上述优化方法和不采用优化方法的两套系统进行测试。在其他条件相同的情况下,相同业务
笔数、相同时间内,死锁发生的情况如下:
采用优化方法的系统: 0次/万笔业务;
不采用优化方法的系统:50~200次/万笔业务。
所以,使用上述优化方法后,特别是在系统高负荷运行时效果尤为显着。总之,在设计、开发数据库应用系统,尤其是OLTP系统时,应该根据
应用系统的具体情况,依据上述原则对系统分别优化,为开发一套高效、可靠的应用系统打下良好的基础。
经验:
1:前台问题:检视代码查看事物是否被提交或回滚。
2:后台问题:有时候由于处理的问题复杂度高。数据库日志空间已满或不够
导致事物未能提交。UNIX下的SYBAE就是典型的一例。解决办法各数据库厂商有更详细的说明。
虽然我从9转到10遇到了好多问题,也浪费了好几天的时间,但到了现在,我真觉得10比9好。
10没有了MSSQL专用接口,用的是OLEDB接口,用这个接口一定要注意一个问题是表死锁的事!
网上讲的连接方式都是天下一大抄。
用OLEDB要加上 SQLCA.Lock = "RC",
不然连查询也会死锁。
另个一个就是10写的软件不再乱码了,我在繁体写的软件在简体下运行不乱码,反之也可以。
第三就是编译速度明显快很多。
第四就是编译的时候有了XP样式皮肤,感觉漂亮多了。
编程要是要养成好习惯,在sql语句insert和update之后,要及时commit,数据窗口update()后也要及时commit;
阻塞是因为多个进程对同一一个资源的访问冲突,当一个进程排它访问一个资源时(从进入事务到事务结束为止),当有其他进程需要访问同
样的资源时,即造成阻塞(根据锁的级别和粒度设置);
在实际应用中阻塞可能因为事务没有提交或者网络速度太慢或者大容量的数据查询等都可能会造成阻塞。
阻塞可以通过sp_who 系统存储过程进行查看,执行sp_who 后查看所有blk不等于
0的进程ID(SPID),直到找到SPID在blk列出现,但当前spid 的blk列 =0 即它就是阻塞的源头。
最简单的办法可用 kill spid(源头进程的SPID值),同时结合sp_lock过程可查看到当前进程的加锁情况(如锁的类型被锁的对象)
最后最重要的是要根据 在查询到源头后,使用 DBCC INPUTBUFFER (spid)查看最后一次提交的内容,即可找到因为事务没有提交造成的阻塞(
一般不能使用 AutoCommit=True,因为大部分MIS程序需要使用批提交,来保证数据的完成性)
http://www.51onnet.com/bbs/forumdisplay.php?f=6
你可能平时编程时没有注意。在 SQLCA(Transaction)默认情况下 AutoCommit = false(不自动提交)。在同一事务中,如果不提交事务,
可以SELECT、Retrieve,但其它事务(其它计算机的应用程序连接数据库的事务)就不能。所以导致死锁,而在单机开发环境看不出来。
你需要在所有的 UPDATE、DELETE 的SQL语句后面,或者数据窗口的Update函数调用之后执行 COMMIT 或 ROLLBACK
死锁可能存在的原因及解决办法
一次偶然的机会在论坛上看到一个关于死锁(其实是阻塞)的帖子,于是把自己的一个小东东拿出来和大家分享,想不到很多人都遇到过这个
问题。
其实解锁并不是根本的解决办法,感觉我自己有点误导大家了,于是有了下面的内容,希望大家能根据自己的应用找出根源,而不是解锁:
阻塞可能存在的原因及解决方法:
1、事务未提交
这是造成阻塞最常见的原因,因为PB默认是自动启动事务的,如果你执行了 update,delete ,insert 语句,不执行Commit 则会出现阻塞(
不建议采用自动提交事务的方式,原因在上一帖中交代过),解决的办法很简单,查找到所有的修改数据命令(U、I、D)查看是否正常提交,找
到后加入Commit即可;
2、SQL SERVER 没有正常安装SP3
对于代码正常的用户,仍然出现阻塞,则需要检查你机器的补丁,特别是WIN2003的机器不安装补丁,1433都不能监听;如果没有安装补丁
即可(我原来就是被这种情况害过)
3、当然可能你会告诉我,代码也没有问题,补丁也装了,仍然出现可能就需要查看你的机器的CPU和内存的使用率(运行taskmgr),SQL
SERVER 的机器峰值状态可能出现阻塞,解决的办法就是出钱:升级服务器;
4、复杂的查询或者大容量查询,比如在查询中使用多个表的联合查询,或者使用 in ,not in 等语句,是非常耗时的,这种解决的办法稍微复
杂点,需要根据你的应用修改SQL 语句,优化SQL 效率,关于SQL 优化是另外一个复杂的话题,本人也学习中...
能想起的好象就这些了,可能不是很完善,希望有人能补充!
你可能平时编程时没有注意。在 SQLCA(Transaction)默认情况下 AutoCommit = false(不自动提交)。在同一事务中,如果不提交事务,
可以SELECT、Retrieve,但其它事务(其它计算机的应用程序连接数据库的事务)就不能。所以导致死锁,而在单机开发环境看不出来。
你需要在所有的 UPDATE、DELETE 的SQL语句后面,或者数据窗口的Update函数调用之后执行 COMMIT 或 ROLLBACK
补充一点,除了在执行了Update,Delete,Insert需要及时Commit外,在SQL Server中由于使用一个Tempdb的数据库,这个数据库是对所有用户共享
的,当使用了统计类型的SQL函数如:sum,count等,SQL Server会自动使用Tempdb进行暂存统计数据,这样很容易造成Tempdb被锁住,所以在读取了
一个很复杂Store Procere或创建过临时表后应进行commit,以便释放Tempdb资源,在retrieved事件中加commit是一个解决办法,特别是在读取
报表后更应加,一般报表的Store Procere都比较复杂,在程序中内嵌了SQL光标来读取数据后也要加commit,我增经试过被锁住,找了很久才知
‘贰’ SQL数据库总是假死或死锁。
建议:
1、使用事件探查器,跟踪一下SQL在死锁之前执行了哪些SQL语句
2、多数死锁是因为程序没有经过严格的测试造成的
3、少部分原因是因为触发器嵌套造成的,SQL有内部机制,当嵌套到一定的层级,就自动终止掉相关的进程
愿早日解决问题
‘叁’ SQL2000 数据库死锁问题
还是通过查看系统表里找出阻塞者直接杀掉阻塞者吧。
select * from master.dbo.sysprocesses
blocked列大于0的,就是被其它进程阻塞了,数值就是进程号,就是sp_who的spid列,可以直接kill这个阻塞者,假设blocked值是55,则kill 55。
建议不要急于kill相关的阻塞进程,用dbcc inputbuffer(55)查看55号进程在执行什么操作,如果是程序编写有问题,最好修改。
‘肆’ sql if update()触发器问题
触发器的触发条件仅仅是数据改变操作是否执行了,即一旦执行insert、update、delete三种命令之一,就要触发。
在update触发器中,通过if update()来过滤,看看是否需要采取什么相应动作,这种逻辑正常、合理呀。
‘伍’ 触发器导致死锁问题,在线求助
一个很简单的场景,但发现如果多用户操作,极易出现死锁现象,特向高手求助,造成锁表的原因,以及如何解决锁表问题。
‘陆’ SQL进程堵塞了,怎么处理
SQL Server 的内存管理机制是:
有可用内存, 则为新需求分配内存
无可用内存时, 释放内存来处理新需求.
这是SQL Server 缓冲池的预期行为。
默认情况下,在启动 SQL Server之后,SQL Server会根据操作系统报告的物理内存数来动态增大或缩小高速缓冲存储器的容量。
只要可用物理内存大小保持在4MB到10MB之间,SQL Server 缓冲池就会继续增大(保留可用物理内存在4MB到10MB之间是为了
避免操作系统因为缺少内存而频繁地换页)。如果物理可用内存变得较少的时候,则SQL Server会将一些内存释放给操作系统。
解决方案:
1.给操作系统、sql server打最新补丁
2.确保不是病毒原因(可能性比较小)
3.sql server设计时的要求就是最大可能的减少磁盘的I/O,磁盘I/O是比较消耗资源的,这个磁盘I/O包括了读取数据库文件
还有和虚拟内存的页交换。如果还有足够的可用内存它都会毫不吝啬的使用的(没有设置上限),它会根据需要动态获取和
释放内存的。你要分析的是这占用的内存开销主要用做了什么?是不是有大型的查询或事务操作。
4.如果服务器是专职的数据库服务器,不建议设置最大内存上限。如果还有其它重要的服务在机器上运行,就要考虑它的内存
使用是否会影响其它服务的正常的运行和性能。如果你的服务器除了sql服务, 还有其他服务需求, 则需要设置sql server的最大内存限制
‘柒’ 如何删除 sql2000 死锁
SQL死锁大部分情况下还是因为SQL语句导致的,所以你得调查一下经常是操作到哪一步的时候死锁的.其中最现概率最大的应该是触发器和存储过程之间了,所以你得检查一下看看这两张中哪些程序有BUG.这个不能靠别人,只能自己慢慢的去摸索,去探测..
‘捌’ 触发器导致死锁问题,在线求助
1编程的时候对死锁多加注意,相应增加代码解决2实际使用时,可以手工从sql管理器里面解锁3因为页面级锁第一个程序打开页面操作,马上就关闭的话,后面再打开就不会引起锁定了。所以主要是程序编写不完善出现的,SQL语句造成的少之又少。
‘玖’ SqlServer2000中多个触发器能否对同一张表进行同时操作
只要在同一事务中的语句操作触发的游标,就不会有死锁问题
另外这多个触发器不能同时对多个表进行不同顺序的更新
比如触发器1 按顺序更新 a,b,c 三个表
但是触发器2 按顺序更新 c,a,b
而触发器3的顺序是 a,c,b
‘拾’ SQL触发器绑定值的问题。。。救命啊。。。弄了一天了
1.你的表设计有问题,USER表完全不需要 grade字段,因为它是多余的,可能不符合第三范式。
2.个人认为触发器无法完成你要的操作。因为如果触发器和update操作的是同一条记录的话,会产生死锁。
最好的方法就是,在更新mark的语句中同时更新grade的值。