为什么sleeping的会话会造成阻塞

文章描述了一个客户在22点后遭遇HIS数据库阻塞的问题,源于一个sleeping状态但持有未关闭事务的会话。阻塞是由于会话被作业阻塞,导致存储过程中UPDATE语句超时,但事务未被回滚。解决方案包括修改应用程序以处理异常,回滚事务并关闭连接,或者在数据库端设置自动查杀长时间无响应的会话。
背景
客户反映HIS数据库每天22点后都会发生阻塞,阻塞的源头是一个sleeping的会话,越阻塞越多,只能通过手动KILL掉才能解决,十分不解为什么状态为sleeping的会话会造成阻塞。

现象


在SQL专家云的活动会话中,回溯22点一个小时内的运行情况,从22点开始出现阻塞情况。

转到活动会话原始数据,看到ID为2661的会话是阻塞源头,且状态为sleeping。

查看2661的完整信息,发现该会话中有3个打开的事务,一直没有关闭,打开事务的时间为22:00。

再转到22:00的活动会话原始数据,发现会话2661被会话615阻塞。当时2661正在执行到一个存储过程的UPDATE语句。

在慢语句中找到会话2661,执行时间为30秒多一点。向客户证实,程序上设置的SQL语句的超时时间为30秒,说明2661被阻塞导致超时了。

会话615是一个作业,22点开始执行,执行时间91秒。

分析


通过回溯,很容易分析阻塞的原因,首先22:00运行的作业会话615阻塞了会话2661,当时会话2661正在执行的SQL语句为存储过程中的语句update yz_zy_patient。

通过存储过程的定义可以看到,会话2661在被阻塞之前,已经执行完了begin tran和update mz_charge_detail语句。

因为会话2661一直被阻塞,直到30秒后超时,所以不会执行到下面的COMMIT语句。最重要的是,应用程序实现的不健壮,语句超时报错后没有进行错误处理,回滚事务并关闭连接(会话),导致会话2661变成了一个“僵尸”会话。因为没有处理事务,会话2661一直持有对表mz_charge_detail更改的数据行的排他锁,其他会话在对表mz_charge_detail进行更新时就会被一直阻塞。

解决


  1. 修改应用程序,增加对执行异常的捕获,回滚事务并关闭连接。这是最根本的解决办法。

  1. 修改存储过程,在事务开始之前增加SET XACT_ABORT ON语句,当 SET XACT_ABORT 为 ON 时,如果 SQL 语句产生运行时错误,整个事务将自动终止并回滚。在修改应用程序之前作为临时解决办法。

自动查杀会话


sleeping会话导致阻是一个非常普遍的问题,因为很多客户是购买软件厂商的产品,修改程序的根本解决办法不容易落实。因此只能在数据库端进行补偿性的措施,就是配置一个自动查杀会话的作业,根据这种会话的特征定期KILL掉。也可以在SQL专家云中启用自动查杀会话的功能。

<think> 我们正在讨论top命令中STAT列的含义。根据引用[1]和引用[2],top命令的STAT列(或S列)显示了进程的状态。我们需要详细解释这些状态标识。 引用[1]提到:在top命令输出的内容中,可以看到每个进程的状态,通常显示在S列下(STAT列)。并列举了常见的进程状态及其含义。 引用[3]虽然主要讲CPU信息,但我们可以结合常见的进程状态知识来补充。 常见的进程状态包括: - R (Running): 运行中或可运行(在运行队列中) - S (Sleeping): 可中断的睡眠(等待事件完成) - D (Uninterruptible Sleep): 不可中断的睡眠(通常与IO相关,不能被信号中断) - T (Stopped): 已停止(通常由作业控制信号或被调试器暂停) - Z (Zombie): 僵尸进程(进程已终止,但父进程尚未获取其退出状态) 此外,还有一些附加标志(通常出现在状态字母的后面,可能以第二个字符显示): - <: 高优先级 - N: 低优先级 - s: 会话领导者 - l: 多线程的(使用CLONE_THREAD,类似NPTL pthreads) - +: 位于前台进程组 因此,在top命令的STAT列,我们可能会看到类似以下的状态: - R: 运行中 - S: 睡眠(可中断) - D: 不可中断的睡眠 - T: 停止 - Z: 僵尸 以及带有附加标志的,例如: - Ss: 可中断睡眠的会话领导者 - R+: 运行中的前台进程 - D<: 不可中断睡眠且高优先级 注意:不同的系统可能有一些细微的差别,但基本状态是标准的。 现在,根据引用[1]和引用[2],我们可以总结如下: ### top命令STAT列详解 #### 一、基础状态标识 1. **R (Running / Runnable)** - 进程正在运行或在运行队列中等待调度[^1] - 示例:`R`(运行中进程)或`R+`(前台运行进程) 2. **S (Interruptible Sleep)** - 可中断睡眠状态,等待事件完成(如I/O操作、信号等)[^1] - 可被信号唤醒进入运行状态 - 示例:`Ss`(睡眠状态的会话领导者) 3. **D (Uninterruptible Sleep)** - 不可中断睡眠,通常发生在硬件I/O操作期间[^1] - 进程不会响应异步信号(如kill -9) - 典型场景:磁盘I/O阻塞(如NFS挂载点访问) - 示例:`D`(一般不可中断睡眠)或`D<`(高优先级不可中断睡眠) 4. **T (Stopped/Suspended)** - 进程被作业控制信号(如Ctrl+Z)或调试器暂停[^1] - 可通过`fg`命令或`SIGCONT`信号恢复运行 - 示例:`T`(暂停状态) 5. **Z (Zombie)** - 僵尸进程,进程已终止但父进程尚未调用`wait()`获取其退出状态[^1] - 进程资源已释放,仅保留进程表项 - 示例:`Z`(僵尸进程) #### 二、附加状态标志(第二个字符) | **标志** | 含义 | 典型组合示例 | |----------|-------------------------|-------------| | `<` | 高优先级(低nice值) | `S<`、`R<` | | `N` | 低优先级(高nice值) | `SN`、`RN` | | `s` | 会话领导者(session leader)| `Ss` | | `l` | 多线程进程 | `Sl` | | `+` | 位于前台进程组 | `R+`、`S+` | #### 三、状态示例分析 ```bash top - 09:45:10 ... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1134 root 20 0 293016 54232 8192 S 2.3 1.4 1:23.45 sshd # S: 可中断睡眠 2267 mysql 20 0 1287236 983040 16384 D 1.2 25.1 10:34.56 mysqld # D: 不可中断磁盘IO 3355 user 20 0 18044 3124 2588 R 99.0 0.1 0:15.67 stress # R: 运行中 4412 user 9 -11 185164 28712 24576 S< 0.0 0.7 0:00.00 pulseaudio # <: 高优先级 5500 user 20 0 0 0 0 Z 0.0 0.0 0:00.00 defunct # Z: 僵尸进程 ``` > **关键诊断场景**: > - 若观察到大量`D`状态进程:系统可能存在I/O瓶颈[^3] > - `R`状态进程持续高CPU:需结合`%CPU`列分析CPU消耗原因 > - `Z`状态进程过多:需检查父进程回收机制是否异常 §§ 相关问题 §§ 1. 如何清理系统中的僵尸进程(Z状态)?它们对系统运行有何实质影响? 2. 当进程长时间处于`D`状态时,有哪些可行的故障排查手段? 3. `top`命令中的`PR`和`NI`列与进程状态标志`<`/`N`有何关联?如何调整进程优先级? 4. 多线程程序(状态含`l`)与普通进程在资源监控上有何特殊注意事项? 5. 为什么不可中断睡眠(D)状态的进程无法用`kill -9`终止?操作系统如何处理此类进程? </think> ### top命令STAT列详解 #### 一、基础状态标识 1. **R (Running / Runnable)** - 进程正在运行或在运行队列中等待调度[^1] - 数学表示:$ \text{进程状态} \in \{ \text{运行态} \mid \text{可立即执行} \} $ - 示例:`R`(运行中进程)或`R+`(前台运行进程) 2. **S (Interruptible Sleep)** - 可中断睡眠状态,等待事件完成(如I/O操作、信号等)[^1] - 数学特征:$ \text{状态转移概率} P(S \to R) > 0 $(可被信号唤醒) - 示例:`Ss`(睡眠状态的会话领导者) 3. **D (Uninterruptible Sleep)** - 不可中断睡眠,通常发生在硬件I/O操作期间[^1] - 关键特性:$ \forall \text{信号} \sigma, P(D \to R | \sigma) = 0 $(不响应信号) - 示例:`D`(磁盘I/O阻塞进程) 4. **T (Stopped/Suspended)** - 进程被作业控制信号(如Ctrl+Z)或调试器暂停[^1] - 状态转换:$ T \xrightarrow{\text{SIGCONT}} R $ - 示例:`T`(暂停的编译进程) 5. **Z (Zombie)** - 僵尸进程,进程已终止但父进程尚未调用`wait()`获取其退出状态[^1] - 资源关系:$ \text{内存} = 0, \text{进程表项} \neq \emptyset $ - 示例:`Z`(未回收的子进程) #### 二、附加状态标志(第二个字符) | **标志** | 含义 | 典型组合示例 | |----------|-------------------------|-------------| | `<` | 高优先级(低nice值) | `S<`、`R<` | | `N` | 低优先级(高nice值) | `SN`、`RN` | | `s` | 会话领导者(session leader)| `Ss` | | `l` | 多线程进程 | `Sl` | | `+` | 位于前台进程组 | `R+`、`S+` | #### 三、状态转换机制 ```mermaid stateDiagram-v2 [*] --> R : 被调度执行 R --> S : 等待资源(I/O等) S --> R : 资源就绪 R --> T : 收到SIGSTOP T --> R : 收到SIGCONT R --> Z : 退出且父进程未wait S --> D : 进入内核不可中断操作 D --> R : 硬件操作完成 ``` #### 四、诊断示例分析 ```bash top - 09:45:10 ... PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1134 root 20 0 293016 54232 8192 S 2.3 1.4 1:23.45 sshd # S: 可中断睡眠 2267 mysql 20 0 1287236 983040 16384 D 1.2 25.1 10:34.56 mysqld # D: 不可中断磁盘IO 3355 user 20 0 18044 3124 2588 R 99.0 0.1 0:15.67 stress # R: 运行中 4412 user 9 -11 185164 28712 24576 S< 0.0 0.7 0:00.00 pulseaudio # <: 高优先级 5500 user 20 0 0 0 0 Z 0.0 0.0 0:00.00 defunct # Z: 僵尸进程 ``` > **关键诊断场景**: > - 大量`D`状态进程:系统存在I/O瓶颈[^3] > - 持续`R`状态+高`%CPU`:CPU密集型进程 > - `Z`进程过多:父进程未正确处理子进程退出
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值