sql存储过程死锁
‘壹’ sql数据库的问题。运行存储过程的时候出现死锁 该怎么解决高分悬赏 只求解答。查跟杀死锁的代码是什么
lock
Select V$SESSION.SID, DBA_OBJECTS.OBJECT_NAME, V$SESSION.OSUSER, V$SESSION.PROGRAM
From V$LOCKED_OBJECT
Left Join DBA_OBJECTS on V$LOCKED_OBJECT.OBJECT_ID = DBA_OBJECTS.OBJECT_ID
Left Join V$SESSION ON V$LOCKED_OBJECT.SESSION_ID = V$SESSION.SID
Order By V$SESSION.SID, DBA_OBJECTS.OBJECT_NAME
unlock(kill session)
alter system kill session 'sid,serial#';
‘贰’ sql server 2008死锁与阻塞怎样解决
MSDN:包含正在 SQL Server 实例上运行的进程的相关信息。这些进程可以是客户端进程或系统进程。 视图中主要的字段: 1. Spid:Sql Servr 会话ID 2. Kpid:Windows 线程ID 3. Blocked:正在阻塞求情的会话 ID。如果此列为 Null,则标识请求未被阻塞 4. Waittype:当前连接的等待资源编号,标示是否等待资源,0 或 Null表示不需要等待任何资源 5. Waittime:当前等待时间,单位为毫秒,0 表示没有等待 6. DBID:当前正由进程使用的数据库ID 7. UID:执行命令的用户ID 8. Login_time:客户端进程登录到服务器的时间。 9. Last_batch:上次执行存储过程或Execute语句的时间。对于系统进程,将存储Sql Server 的启动时间 10.Open_tran:进程的打开事务个数。如果有嵌套事务,就会大于1 11.Status:进程ID 状态,dormant = 正在重置回话 ; running = 回话正在运行一个或多个批处理 ; background = 回话正在运行一个后台任务 ; rollback = 会话正在处理事务回滚 ; pending = 回话正在等待工作现成变为可用 ; runnable = 会话中的任务在等待获取 Scheler 来运行的可执行队列中 ; spinloop = 会话中的任务正在等待自旋锁变为可用 ; suspended = 会话正在等待事件完成 12.Hostname:建立链接的客户端工作站的名称 13.Program_name:应用程序的名称,就是 连接字符串中配的 Application Name 14.Hostprocess:建立连接的应用程序在客户端工作站里的进程ID号 15.Cmd:当前正在执行的命令 16.Loginame:登录名 应用实例: 1. 检查数据库是否发生阻塞 先查找哪个链接的 blocked 字段不为0。如 SPID53的blocked 字段不为0,而是 52。SPID 52 的 blocked 为0,就可以得出结论:此时有阻塞发生,53 被 52 阻塞住了。如果你发现一个连接的 blocked 字段的值等于它自己,那说明这个连接正在做磁盘读写,它要等自己的 I/O 做完。 2. 查找链接在那个数据库上 检查 dbid 即可。得到 dbid,可以运行以下查询得到数据库的名字: Select name,dbid from master.sys.sysdatabases
‘叁’ 存储过程可以解决数据库死锁问题吗 sqlserver2008
清空日志
DUMP TRANSACTION 库名
WITH
NO_LOG
2.截断事务日志:
BACKUP LOG 数据库名 WITH
NO_LOG
3.收缩数据库文件
数据库名--右击--任务--收缩--文件
--文件类型选择日志--收缩操作选择第二个 将文件收缩到0 ,确定就可以了
4. 也可以用SQL语句来完成
--收缩数据库
DBCC SHRINKDATABASE(客户资料)
--收缩指定数据文件,1是文件号,可以通过这个语句查询到:select * from
sysfiles
DBCC SHRINKFILE(1)
收缩的时候把恢复模式改为简单 否则收缩不了
希望解决了楼主的问题
‘肆’ SQL数据库表的死锁问题
死锁的原因可能有多个。
可能第一个人更新的时候,第二个人尝试读取,第二个人就卡住了。
假如第一个人更新了,还没提交,又去检索一些别的数据,这些数据又是被第三个人锁定的...
SQL Server 多用户之间锁的处理
http://hi..com/wangqing999/blog/item/245768d895cf84b0cc11662b.html
上面这个帖子演示一个 多用户数据锁定 / 死锁 的例子.
C# 多线程处理 IV 线程安全
http://hi..com/wangqing999/blog/item/6c40f05df135e83a2834f0fc.html
这个帖子,提供一个 C# 中,如果通过同步处理, 确保某个 资源,在一个时间点上,只有一个用户可以使用的例子。
‘伍’ 如何查看死锁的”SQL语句“或”存储过程“
假如发生了死锁,我们怎么去检测具体发生死锁的是哪条SQL语句或存储过程?此时我们可以使用以下存储过程来检测,就可以查出引起死锁的进程和SQL语句。
Sql代码
usemaster
go
create proceresp_who_lock
as
begin
declare @spid int,@blint,
@intTransactionCountOnEntryint,
@intRowcountint,
@intCountPropertiesint,
@intCounter int
create table #tmp_lock_who(
id intidentity(1,1),
spidsmallint,
blsmallint)
IF @@ERROR<>0 RETURN@@ERROR
insert into#tmp_lock_who(spid,bl) select 0 ,blocked
from (select * fromsysprocesses where blocked>0 ) a
where not exists(select *from
(select * from sysprocesseswhere blocked>0 ) b
wherea.blocked=spid)
union select spid,blockedfrom 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
begin
-- 取第一条记录
select @spid = spid,@bl =bl
from #tmp_lock_who where Id= @intCounter
begin
if @spid=0
select '引起数据库死锁的是: '+ CAST(@bl ASVARCHAR(10))
+ '进程号,其执行的SQL语法如下'
else
select '进程号SPID:'+ CAST(@spid AS VARCHAR(10))
+ '被进程号SPID:'+ CAST(@bl ASVARCHAR(10))
+ '阻塞,其当前进程执行的SQL语法如下'DBCC INPUTBUFFER
use master
go
create proceresp_who_lock
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntryint,
@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 * fromsysprocesses where blocked>0 ) a
where not exists(select *from
(select * from sysprocesseswhere blocked>0 ) b
where a.blocked=spid)
union select spid,blockedfrom 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
begin
-- 取第一条记录
select @spid = spid,@bl =bl
from #tmp_lock_who where Id= @intCounter
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
与锁定有关的两个问题--死锁和阻塞
‘陆’ sql提示死锁
我也曾遇到过这个问题,记得当时我写了一个复杂的存储过程,里面处理了很多个数据表的数据,且在存储过程中使用了事务。
该存储过程在查询分析器中执行需要20秒左右的时间。但到程序中去执行,所需要的时间就要长很多了。而且由于采用事务,容易产生死锁。问题与你的一样。
后来我采取了以下措施,问题便得到改状况,至目前为止没有再出现过此问题:
将你的存储过程进行优化,将需要的数据取到存储中,使用临时表或变量保存,而对于插入数据、删除数据、修改数据、等需要事务的地方,则开启事务,在此之前的处理中,不要使用事务。
另外就是尽量减少对大数据量表的操作次数,优化各句话,使其执行时间快,效率优。尽量降低存储过程的运行时间。减少数据表在事务中锁定的时间。
祝你成功
‘柒’ sql处理数据库锁的存储过程分享
邹建
2004.4
复制代码
代码如下:
/*--调用示例
exec
p_lockinfo1
--*/
alter
proc
p_lockinfo1
@kill_lock_spid
bit=1,
--是否杀掉死锁的进程,1
杀掉,
0
仅显示
@show_spid_if_nolock
bit=1
--如果没有死锁的进程,是否显示正常进程信息,1
显示,0
不显示
as
declare
@count
int,@s
nvarchar(max),@i
int
select
id=identity(int,1,1),标志,
进程ID=spid,线程ID=kpid,块进程ID=blocked,数据库ID=dbid,
数据库名=db_name(dbid),用户ID=uid,用户名=loginame,累计CPU时间=cpu,
登陆时间=login_time,打开事务数=open_tran,
进程状态=status,
工作站名=hostname,应用程序名=program_name,工作站进程ID=hostprocess,
域名=nt_domain,网卡地址=net_address
into
#t
from(
select
标志='死锁的进程',
spid,kpid,a.blocked,dbid,uid,loginame,cpu,login_time,open_tran,
status,hostname,program_name,hostprocess,nt_domain,net_address,
s1=a.spid,s2=0
from
master..sysprocesses
a
join
(
select
blocked
from
master..sysprocesses
group
by
blocked
)b
on
a.spid=b.blocked
where
a.blocked=0
union
all
select
'|_牺牲品_>',
spid,kpid,blocked,dbid,uid,loginame,cpu,login_time,open_tran,
status,hostname,program_name,hostprocess,nt_domain,net_address,
s1=blocked,s2=1
from
master..sysprocesses
a
where
blocked<>0
)a
order
by
s1,s2
select
@count=@@rowcount,@i=1
if
@count=0
and
@show_spid_if_nolock=1
begin
insert
#t
select
标志='正常的进程',
spid,kpid,blocked,dbid,db_name(dbid),uid,loginame,cpu,login_time,
open_tran,status,hostname,program_name,hostprocess,nt_domain,net_address
from
master..sysprocesses
set
@count=@@rowcount
end
if
@count>0
begin
create
table
#t1(id
int
identity(1,1),a
nvarchar(max),b
Int,EventInfo
nvarchar(max))
if
@kill_lock_spid=1
begin
declare
@spid
varchar(max),@标志
varchar(max)
while
@i<=@count
begin
select
@spid=进程ID,@标志=标志
from
#t
where
id=@i
insert
#t1
exec('dbcc
inputbuffer('+@spid+')')
if
@标志='死锁的进程'
exec('kill
'+@spid)
set
@i=@i+1
end
end
else
while
@i<=@count
begin
select
@s='dbcc
inputbuffer('+cast(进程ID
as
varchar(max))+')'
from
#t
where
id=@i
insert
#t1
exec(@s)
set
@i=@i+1
end
select
a.*,进程的SQL语句=b.EventInfo
from
#t
a
join
#t1
b
on
a.id=b.id
end
go
‘捌’ 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 SERVER一个数据库中使用大量的存储过程,会影响性能吗
一、在SQL Server中存储过程不会影响性能。
1、只会大大的减轻服务器的压力,而不会增加,只有不合理的存储过程才会造成服务器性能下降的恶果。一个大型的数据库,一般存储过程也不会超过几千个,对当前的数据库及它依附的硬件来说,这点儿负载是大象身上的老鼠,负载基本可以怱略不计。
2、但是,存储过程是批量的SQL语句的合成,如果设计上混乱,引发死循环、死锁、大范围查询、临时表没有及时清理释放等问题的情况下,是会严重影响服务器性能的,但这根子不在存储过程上,而在于存储过程的设计上。错误的SQL代码指挥服务器,无论它的形式是存储过程,还是客户端及时发向数据库的请求,都会使服务器出现问题。
二、相关扩展
1、在当前,针对数据库的编程设计,没有存储过程是不可想象的,这就象某个公司的大型货品仓库中没有仓库保管员一样,所有的货品进出都得进货员或销售员去临时取放,会严重降低工作效率。
2、存储过程在数据库中无论是否编译好,其效率都要比客户端临时向数据库发送指令调数据来得要高,因为至少减少了发向服务器的指令的量。况且很多的中间值、临时值如果不通过存储过程来实现的话,就只能先全取到客户端,这样会大大增加网络负担与服务器的负钽。
3、正如微软所说,存储过程来实现,可以使得很多中间量不必传入到客户上,客户端只能得到需要的结果,所以同时可以提高安全。