一个数据库解锁的存储过程sp_who_lock

博客给出了一个用 SQL 编写的存储过程 sp_who_lock,用于查询数据库中的死锁和阻塞信息。该过程创建临时表存储相关进程信息,通过循环遍历临时表,输出引起死锁的进程号及对应执行的 SQL 语法,最后删除临时表。
将所有死锁死锁死锁id找出来,然后再kill。

SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS OFF
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
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 (@bl )
end

-- 循环指针下移
set @intCounter = @intCounter + 1
end


drop table #tmp_lock_who

return 0
end
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO

<think>首先,用户的问题是:“我想了解同一个线程是否可以调用pthread_mutex_lock进行嵌套。请问同一个线程能否嵌套调用pthread_mutex_lock?” 用户明确询问同一个线程是否可以嵌套调用pthread_mutex_lock。这意味着在同一个线程中,多次调用pthread_mutex_lock函数而不先解锁。 现在,回顾系统指令: - 所有行内数学表达式用$...$格式。 - 独立公式用$$...$$并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 - 结构清晰,帮助用户逐步解决问题。 - 参考站内引用:用户提供了几个引用: - [^1]: 关于PTHREAD_MUTEX_ROBUST,但用户的问题是嵌套调用,与robust相关度不高。 - [^2]: 关于避免死锁的顺序锁,展示了代码片段。 - [^3]: 提到锁不能被两个不同线程同时拥有,对于普通锁和适应锁,解锁者可以是任何线程;对于检错锁和解锁,有特定要求;嵌套锁允许同一个线程多次加锁。 - [^4]: 描述了互斥锁的类型,包括PTHREAD_MUTEX_RECURSIVE_NP用于嵌套锁。 从引用[^3]和[^4]中,直接相关的是: - 引用[^3]说:"对于嵌套锁,文档和实现要求必须由加锁者解锁,但实验结果表明并没有这种限制,这个不同目前还没有得到解释。" - 引用[^4]说:"PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次 unlock 解锁。" 所以,关键点是:是否允许嵌套调用取决于互斥锁的类型。 具体来说: - 普通锁(PTHREAD_MUTEX_TIMED_UP):不允许嵌套。如果同一个线程尝试再次加锁,可能会导致死锁或其他错误。 - 嵌套锁(PTHREAD_MUTEX_RECURSIVE_NP):允许同一个线程多次加锁和解锁。 - 检错锁(PTHREAD_MUTEX_ERRORCHECK_NP):会返回错误EDEADLK如果同一个线程尝试嵌套加锁。 - 适应锁(PTHREAD_MUTEX_ADAPTIVE_NP):行为简单,可能在解锁后竞争,但不支持嵌套。 因此,回答应该是:是的,同一个线程可以嵌套调用pthread_mutex_lock,但前提是互斥锁的类型是PTHREAD_MUTEX_RECURSIVE_NP。对于其他类型,它可能会导致问题如死锁或错误。 现在,构建回答: - 结构清晰:先直接回答问题,然后解释原因和细节。 - 使用中文。 - 添加引用:在相关部分自然地添加[^3]和[^4],因为这是直接从引用中得来的。 - 生成相关问题:在末尾添加相关问题。 步骤: 1. **直接回答**:简要陈述能否嵌套。 2. **解释细节**:基于互斥锁类型说明。 3. **代码示例**:如果需要,展示如何创建递归锁(但用户没有要求代码,所以可选)。 4. **注意事项**:强调类型的重要性。 5. **相关问题**:生成2-3个相关问题。 最终回答大纲: - 开头:是的,同一个线程可以嵌套调用pthread_mutex_lock,但需要互斥锁被初始化为递归类型。 - 详细解释: - 引用[^4]定义了PTHREAD_MUTEX_RECURSIVE_NP。 - 引用[^3]提到嵌套锁允许同一个线程多次加锁。 - 对于非递归类型,尝试嵌套会导致死锁或错误。 - 结尾:提醒开发者正确初始化锁。 - 相关问题:例如: 1. 如何初始化一个递归互斥锁? 2. 嵌套锁的应用场景有哪些? 3. 如果尝试在非递归锁上嵌套加锁会发生什么? 确保LaTeX:问题中没有数学表达式,所以可能不需要。 引用标识:在解释中引用[^3]和[^4]。 完整回答: - 首先回答问题。 - 然后展开。 - 添加相关问题。 </think>### 同一个线程是否可以嵌套调用 pthread_mutex_lock? 是的,同一个线程可以嵌套调用 `pthread_mutex_lock` 函数,但这**取决于互斥锁的类型**。具体行为如下: 1. **递归锁(嵌套锁)允许嵌套调用**: - 如果互斥锁被初始化为 `PTHREAD_MUTEX_RECURSIVE_NP` 类型(也称为嵌套锁),则同一个线程可以多次调用 `pthread_mutex_lock` 而不解锁。 - 每次调用 `pthread_mutex_lock` 会增加锁的计数,解锁时需要调用 `pthread_mutex_unlock` 相同次数才能完全释放锁。 - 例如:同一个线程在函数 A 中加锁后,调用函数 B(也尝试加锁),不会阻塞自身。 - 这一行为在引用中明确指出:"PTHREAD_MUTEX_RECURSIVE_NP,嵌套锁,允许同一个线程对同一个锁成功获得多次,并通过多次 unlock 解锁" [^4]。 2. **其他锁类型通常不允许嵌套调用**: - **普通锁(`PTHREAD_MUTEX_TIMED_UP`)**:默认类型。同一个线程尝试嵌套调用时,会导致线程死锁(block),因为锁已被自身持有,无法重新获取。 - **检错锁(`PTHREAD_MUTEX_ERRORCHECK_NP`)**:同一个线程尝试嵌套调用时,函数会立即返回错误码 `EDEADLK`(表示死锁风险),而不是阻塞。引用提到:"如果是不同线程请求,则在加锁线程解锁时重新竞争" [^4]。 - **适应锁(`PTHREAD_MUTEX_ADAPTIVE_NP`)**:行为类似普通锁,不支持嵌套调用。 - 引用强调:"对于普通锁和适应锁类型,解锁者可以是同进程内任何线程;而检错锁则必须由加锁者解锁才有效" [^3]。如果尝试在非递归锁上嵌套加锁,可能导致未定义行为或死锁。 3. **如何启用嵌套调用**: - 初始化互斥锁时指定类型为递归锁: ```c pthread_mutex_t mutex; pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); // 设置递归类型 pthread_mutex_init(&mutex, &attr); // 初始化锁 ``` - 这样,同一个线程即可安全嵌套调用 `pthread_mutex_lock`。 4. **注意事项**: - 嵌套调用会增加锁的复杂性,可能导致死锁风险(如忘记解锁次数),因此仅在必要时使用(如递归函数)。 - 非递归锁上尝试嵌套调用是常见错误,引用提到:"在同一进程中的线程,如果加锁后没有解锁,则任何其他线程都无法再获得锁",这同样适用于同一个线程的嵌套场景 [^3]。 - 使用 `pthread_mutex_trylock` 可以检测锁状态,避免阻塞。 总之,同一个线程能否嵌套调用 `pthread_mutex_lock`,关键在于互斥锁的类型:**仅递归锁支持嵌套调用,其他类型可能导致死锁或错误**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值