查看数据库死锁的进程及清除sleeping进程(Kill__Sleeping_Processes)

本文介绍如何使用 SQL Server 的存储过程 `proc_find_lock` 查看数据库死锁的进程,并提供了清除处于睡眠状态的进程 `Kill__Sleeping_Processes` 存储过程的实现方法。通过实例演示了如何运行这些存储过程并分析结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 
例28.49  查看数据库死锁的进程(proc_who_lock)

用proc_ find _lock过程查看数据库死锁的进程。

if exists (SELECT *
           FROM dbo.sysobjects
           WHERE id = object_id(N'[dbo].[proc_find_lock]')
           and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[proc_find_lock]

GO

create procedure proc_find_lock
as
begin
declare @spid int,@bl int,
@intTransactionCountOnEntry int,
         @intRowcount int,
         @intCountProperties int,
         @intCounter int

create table #temp_lock (
id int identity(1,1),
spid smallint,
bl smallint)

IF @@ERROR<>0 RETURN @@ERROR
   INSERT INTO #temp_lock(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 #temp_lock

IF @@ERROR<>0 RETURN @@ERROR
   if @intCountProperties=0
      SELECT '没有阻塞和死锁信息' as 提示

while @intCounter <= @intCountProperties
BEGIN

SELECT @spid = spid,@bl = bl
FROM #temp_lock 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 #temp_lock

return 0

end

运行过程proc_find_lock,结果如图28-48所示。

proc_find_lock

 

例28.46  清除sleeping进程(Kill__Sleeping_Processes)

Sleeping进程是系统中处于睡眠状态尚未活动的进程,这部分进程可以杀掉。

CREATE PROCEDURE dbo.Kill__Sleeping_Processes @dbname varchar(50)

AS

BEGIN

SET NOCOUNT ON

DECLARE @spid INT,

@cnt INT,

@sql VARCHAR(255)

SELECT @spid = MIN(spid),@cnt = COUNT(*)

FROM master..sysprocesses

WHERE dbid = DB_ID(@dbname) AND spid != @@SPID AND status = 'sleeping'

WHILE @spid IS NOT NULL

BEGIN

SET @sql = 'KILL ' + RTRIM(@spid)

EXEC ( @sql )

SELECT @spid = MIN(spid),@cnt = COUNT(*)

FROM master..sysprocesses

WHERE dbid = DB_ID(@dbname) AND spid != @@SPID AND status = 'sleeping'

END

END

GO

运行改存储过程后杀掉sleeping进程:

Kill__Sleeping_Processes SQLS2008

  清除前后可以用EXEC sp_who 'active '进行查看。

 


 

<think>好的,我现在需要解决用户的问题:当SystemUI主线程进行Binder通信时执行耗时7秒,会发生ANR吗? 首先,我要理解ANR(应用无响应)的触发条件。根据Android文档,ANR通常发生在主线程被阻塞超过一定时间。常见的情况包括输入事件5秒内未处理或BroadcastReceiver10秒内未完成。但用户提到的是Binder通信耗时7秒,这属于服务间通信,可能需要特别分析。 接下来,我需要确认Binder通信在主线程中的表现。Binder调用默认是同步的,如果在主线程中执行,会阻塞主线程的其他操作。如果SystemUI的主线程进行了一个耗时7秒的Binder调用,那么在这7秒内主线程无法处理其他事件,如用户输入或系统广播。 然后,我需要考虑ANR的具体触发机制。输入事件导致的ANR是5秒阈值,而Service或BroadcastReceiver有不同的时间限制。但SystemUI作为系统进程,可能有一些例外情况吗?例如,系统进程是否有更高的容忍度,或者某些Binder调用被标记为允许更长时间? 不过,通常来说,任何主线程的长时间阻塞都可能导致ANR。用户提到的7秒明显超过了常见的5秒阈值,因此极有可能触发ANR。但需要确认这个Binder调用是否在等待其他进程的响应,或者是否存在死锁情况,导致主线程无法继续执行。 另外,还要考虑系统对ANR的监控机制。系统会定期检查主线程的消息队列,如果发现某个消息处理时间过长,就会触发ANR对话框。因此,即使Binder调用本身是在处理一个消息,耗时7秒的话,系统应该会检测到并报告ANR。 可能还需要查看具体的日志和traces.txt文件,确认ANR的具体原因。例如,查看堆栈信息是否显示主线程卡在Binder调用上,以及是否有其他线程或进程的问题导致Binder调用延迟。 总结:主线程中的任何长时间阻塞操作,包括Binder通信,如果超过系统设定的时间阈值,就会导致ANR。在这个案例中,7秒的耗时远超过5秒的输入事件阈值,因此极有可能发生ANR。</think>--- ### **1. 结论** **会触发 ANR(Application Not Responding)**。 当 `SystemUI` 主线程的 Binder 通信耗时 **7 秒**,必然会导致主线程阻塞,触发 ANR 弹窗或日志记录。 --- ### **2. ANR 触发机制** Android 系统通过 **`ActivityManagerService`** 监控主线程响应性,关键规则如下: - **输入事件(如点击、滑动)**:主线程 **5 秒内未处理完成**。 - **BroadcastReceiver**:**10 秒内未执行完 `onReceive()`**。 - **Service 生命周期方法(如 `onCreate()`)**:**20 秒内未完成**。 - **Binder 通信(跨进程调用)**:**主线程同步调用超过阈值**(实际依赖系统配置,但通常与输入事件阈值对齐)。 --- ### **3. 问题核心分析** #### **Binder 通信的特性** - **同步性**:默认 Binder 调用是 **同步阻塞** 的(除非显式使用异步 API)。 - **线程关联性**:若在 `SystemUI` 主线程发起 Binder 调用,主线程会被完全阻塞,直到远程服务返回结果。 - **超时风险**:若远程服务响应慢或死锁,主线程将无法处理其他消息(如界面刷新、用户输入)。 #### **耗时 7 秒的直接后果** - **主线程阻塞**:7 秒内,`SystemUI` 无法响应以下操作: - 状态栏交互(下拉通知栏、切换设置) - 导航手势(返回、Home、多任务) - 系统广播处理(如屏幕旋转、电量变化) - **ANR 判定**:系统检测到主线程无响应后,会记录 ANR 事件(`ANR in com.android.systemui`),并可能弹出提示框(取决于系统配置)。 --- ### **4. 复现与验证** #### **查看 ANR 日志** 通过以下命令获取 ANR 详情: ```bash adb shell cat /data/anr/traces.txt ``` 搜索 `com.android.systemui` 进程的堆栈,定位到 **`Binder` 调用阻塞点**,例如: ``` "main" prio=5 tid=1 Native | group="main" sCount=1 dsCount=0 flags=1 obj=0x72e8f7d0 self=0x7c3f9a4a00 | sysTid=12345 nice=-2 cgrp=default sched=0/0 handle=0x7c4f4cb4f0 | state=S schedstat=( 123456789 987654321 12345 ) utm=12 stm=5 core=0 HZ=100 | stack=0x7fc95da000-0x7fc95dc000 stackSize=8192KB | held mutexes= native: #00 pc 000000000007a4d8 /system/lib64/libbinder.so (android::IPCThreadState::waitForResponse(android::Parcel*, int*)+200) native: #01 pc 0000000000078f9c /system/lib64/libbinder.so (android::IPCThreadState::transact(int, unsigned int, android::Parcel const&, android::Parcel*, unsigned int)+180) at android.os.BinderProxy.transactNative (Binder.java) at android.os.BinderProxy.transact (Binder.java:1143) at android.content.pm.IPackageManager$Stub$Proxy.getApplicationInfo (IPackageManager.java:5678) ... ``` #### **关键日志特征** - **线程状态**:`state=S`(Sleeping)或 `state=D`(Uninterruptible Sleep)。 - **堆栈信息**:停留在 `libbinder.so` 的 `waitForResponse` 或 `transact` 函数。 - **阻塞来源**:可能指向某个系统服务(如 `PackageManagerService`、`WindowManagerService`)。 --- ### **5. 根本原因** #### **常见场景** 1. **跨进程服务响应延迟** - 例如:`SystemUI` 调用 `PackageManagerService` 查询应用信息,但对方服务主线程繁忙。 - 可通过 `adb shell dumpsys activity processes` 检查目标服务的线程状态。 2. **死锁(Deadlock)** - `SystemUI` 主线程持有锁 A,请求远程服务的锁 B;而远程服务主线程持有锁 B,同时请求锁 A。 - 使用 `kill -3 <pid>` 生成堆栈,分析锁依赖链。 3. **Binder 线程池耗尽** - 默认 Binder 线程池大小为 **16**,若并发请求过多,新请求会被阻塞。 - 通过 `adb shell ps -t <pid>` 查看目标进程的 Binder 线程数。 --- ### **6. 解决方案** #### **代码优化** - **异步化改造**:将同步 Binder 调用改为异步(如 `AIDL` + `Oneway` 或 `Callback`): ```java // 异步 AIDL 接口定义 interface IRemoteService { oneway void requestData(in Parcelable params); // 非阻塞调用 } ``` - **子线程执行**:使用 `HandlerThread` 或协程(如 Kotlin `CoroutineDispatcher.IO`): ```kotlin lifecycleScope.launch(Dispatchers.IO) { val result = binderProxy.queryData() // 在 IO 线程执行 Binder 调用 withContext(Dispatchers.Main) { updateUI(result) // 回到主线程更新 UI } } ``` #### **系统级调优** - **增加 Binder 线程池**(需修改 `frameworks/base`): ```cpp // 修改 ProcessState.cpp 中的默认线程数 #define DEFAULT_MAX_BINDER_THREADS 32 ``` - **调整 Binder 驱动参数**(需 Root): ```bash echo 64 > /sys/module/binder/parameters/max_threads # 增大线程池上限 ``` #### **监控与防御** - **添加超时机制**:通过 `Handler.postDelayed()` 设置超时回调: ```java final Runnable timeoutTask = () -> { if (!isResponseReceived) { Log.w(TAG, "Binder call timeout!"); recoverFromBlocking(); } }; handler.postDelayed(timeoutTask, 5000); // 5 秒超时 ``` - **WatchDog 监控**:在系统层为关键服务添加 WatchDog 检测(需定制 ROM)。 --- ### **7. 验证修复效果** - **ANR 率监控**:通过 Firebase Crashlytics 或厂商分析工具观察 `SystemUI` 的 ANR 是否减少。 - **性能 Profiling**:使用 Android Studio Profiler 检测主线程阻塞情况: - 查看主线程的 **CPU Usage** 和 **Method Tracing**。 - 确认 Binder 调用耗时降至毫秒级(如 <100ms)。 --- ### **总结** 主线程的 Binder 同步调用耗时 7 秒 **必然触发 ANR**。优化方向包括: 1. **异步化**:避免主线程直接发起跨进程调用。 2. **子线程隔离**:将耗时操作移至工作线程。 3. **系统调优**:调整 Binder 线程池和驱动参数(需 Root 或定制系统)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值