Oracle session active 和 inactive 状态 说明(与死连接检测DCD ,客户端的联接仍然是活动的 有关)

本文详细解释了Oracle数据库中Session的不同状态,包括ACTIVE、INACTIVE、KILLED等,并介绍了如何通过设置SQLNET.EXPIRE_TIME和PROFILE的IDLE_TIME参数来处理INACTIVE状态的Session。
分类: Oracle Basic Knowledge 2011-06-12 13:08 7877人阅读 评论(3) 收藏 举报

 

. Session 状态说明

            可以通过v$session 视图的status列查看session 的状态。  关于该视图的使用,参考联机文档:

V$SESSION

http://download.oracle.com/docs/cd/E11882_01/server.112/e17110/dynviews_3016.htm#REFRN30223

 

 

STATUS

VARCHAR2(8)

Status of the session:

ACTIVE - Session currently executing SQL

INACTIVE

KILLED - Session marked to be killed

CACHED - Session temporarily cached for use by Oracle*XA

SNIPED - Session inactive, waiting on the client

 

 

有关状态的说明:

1active 处于此状态的会话,表示正在执行,处于活动状态。

            官方文档说明:

            Any session that is connected to the database and is waiting for an event that does not belong to the Idle wait class is considered as an active session.

 

2killed处于此状态的会话,被标注为删除,表示出现了错误,正在回滚。

            当然,也是占用系统资源的。还有一点就是,killed的状态一般会持续较长时间,而且用windows下的工具pl/sql developer来kill掉,是不管用的,要用命令:alter system kill session 'sid,serial#' ;

 

3inactive 处于此状态的会话表示不是正在执行的

            该状态处于等待操作(即等待需要执行的SQL语句),通常当DML语句已经完成。 但连接没有释放,这个可能是程序中没有释放,如果是使用中间件来连接的话,也可能是中间件的配置或者是bug 导致。

 

            inactive对数据库本身没有什么影响,但是如果程序没有及时commit,那么就会造成占用过多会话。容易是DB 的session 达到极限值。

            问了几个朋友,他们的做法是不处理inactive 状态的session, 如果达到了session 的最大值, 就增加processes 和 sessions 参数。 如果kill inactive session 可能会到中间件有影响。 具体中间件这块我也不太熟,等以后弄清楚了,在说。

 

 

. 处理inactive 状态的session

            在前面说不处理inactive 状态的session,但是还是有方法来解决的。 有两种方法。

 

2.1 sqlnet.ora文件中设置expire_time 参数

官网有关这个参数的说明:

http://download.oracle.com/docs/cd/B19306_01/network.102/b14213/sqlnet.htm

 

SQLNET.EXPIRE_TIME

Purpose

            Use parameter SQLNET.EXPIRE_TIME to specify a the time interval, in minutes, to send a probe to verify that client/server connections are active. Setting a value greater than 0 ensures that connections are not left open indefinitely, due to an abnormal client termination. If the probe finds a terminated connection, or a connection that is no longer in use, it returns an error, causing the server process to exit. This parameter is primarily intended for the database server, which typically handles multiple connections at any one time.

            sqlnet.expire_time 的原理:Oracle Server 发送包探测dead connection ,如果连接关闭,或者不再用,则关闭相应的server process.

 

Limitations on using this terminated connection detection feature are:

(1)It is not allowed on bequeathed connections.

(2)Though very small, a probe packet generates additional traffic that may downgrade network performance.

(3)Depending on which operating system is in use, the server may need to perform additional processing to distinguish the connection probing event from other events that occur. This can also result in degraded network performance.

 

Default 0

Minimum Value :0

Recommended Value 10

 

Example

SQLNET.EXPIRE_TIME=10

 

 

2.2 设置用户profileidle_time参数

           

之前整理的一篇有关profile的文章:

            Oracle 用户 profile 属性

            http://blog.youkuaiyun.com/tianlesoftware/archive/2011/03/10/6238279.aspx

 

            注意,要启用idle_time 要先启用RESOURCE_LIMIT参数。 该参数默认是False。 官网说明如下:

 

RESOURCE_LIMIT

Property

Description

Parameter type

Boolean

Default value

false

Modifiable

ALTER SYSTEM

Range of values

true | false

 

            RESOURCE_LIMIT determines whether resource limits are enforced in database profiles.

 

Values:

            TRUE: Enables the enforcement of resource limits

            FALSE:Disables the enforcement of resource limits

 

如下blog 在这块说的比较清楚,并提供了相关的脚本:

            sqlnet.expire_time and IDLE_TIME

            http://space.itpub.net/10687595/viewspace-420407

 

 

            IDLE_TIME Specify the permitted periods of continuous inactive time during a session, expressed in minutes. Long-running queries and other operations are not subject to this limit.

 

            A valid database connection that is idle will respond to the probe packet causing no action on the part of the Server , whereas the resource_limit will snipe the session when idle_time is exceeded. The 'sniped' session will get disconnected when the user(or the user process) tries to communicate with the server again.

           

            -- 通过idle_time限制session idle 时间。session idle超过设置时间,状态为sniped (v$session).,然而OS下的process并不会释放,当session(user process) 再次与server process 通讯,将关闭相应的server process.

 

What does 'SNIPED' status in v$session mean?

            When IDLE_TIME is set in the users' profiles or the default profile. This will kill the sessions in the database (status in v$session now becomes SNIPED) and they will eventually disconnect. It does not always clean up the Unix session (LOCAL=NO sessions).

            At this time all oracle resources are released but the shadow processes remains and OS resources are not released. This shadow process is still counted towards the parameters of init.ora.

            This process is killed and entry from v$session is released only when user again tries to do something. Another way of forcing disconnect (if your users come in via SQL*Net) is to put the file sqlnet.ora on every client machine and include the parameter "SQLNET.EXPIRE_TIME" in it to force the close of the SQL*Net session

sqlnet.expire_time

            sqlnet.expire_time actually works on a different principle and is used to detect dead connections as opposed to disconnecting(actually 'sniping') a session based on idle_time which the profile accomplishes.


            But again, as you mentioned, expire_time works globally while idle_time profile works for that user. You can use both of them to make sure that the client not only gets sniped but also gets disconnected if the user process abnormally terminates.

 

修改示例:

SQL>alter profile default limit idle_time 10;

--需要重启下oracle

 

查询应用的连接数SQL:

/* Formatted on 2011/6/12 13:06:23 (QP5 v5.163.1008.3004) */

  SELECT b.MACHINE, b.PROGRAM, COUNT (*)

    FROM v$process a, v$session b

   WHERE a.ADDR = b.PADDR AND b.USERNAME IS NOT NULL

GROUP BY b.MACHINE, b.PROGRAM

ORDER BY COUNT (*) DESC;

 

 

 

 

 

 

 

<think>好的,我需要帮助用户解决在UOS系统中通过脚本自动执行.service文件的相关步骤,并处理service状态显示active但实际上处于inactive的问题。根据用户提供的引用内容之前的对话,我需要综合这些信息来给出解决方案。 首先,用户希望用脚本来自动化创建配置systemd服务。之前的回答中已经提供了一个脚本示例,用于创建brscan_skey.service文件,并处理路径检测、权限、服务激活等步骤。现在用户遇到了服务状态显示active但实际为inactive的问题,需要解决这个问题。 根据引用[1],当服务类型为oneshot时,服务执行完命令后会立即变为inactive状态,这意味着没有active状态。用户的问题可能此相关,或者可能服务配置有误导致服务无法正确保持运行。 接下来,我需要参考用户提供的引用来分析可能的原因解决方案: 1. 引用[1]提到oneshot类型的服务没有active状态,执行完即变为inactive。如果用户的服务是这种类型,那么状态显示为active可能不正确,或者用户期望服务持续运行,这时候可能需要选择不同的Type类型,如simple或forking。 2. 引用[2]中的示例使用了Type=simple,这种情况下systemd认为服务会立即启动,但需要服务进程持续运行。如果服务进程退出,可能会导致状态变为inactive。可能需要检查服务进程是否持续运行,或者是否需要设置Restart策略。 3. 引用[5]提到Restart的配置选项,如on-failure,可以自动重启服务。如果服务意外退出,配置正确的Restart策略可能有助于保持服务状态active。 4. 引用[4]中的步骤提到创建服务文件后需要daemon-reload,enable服务等步骤,这些在脚本中已经处理,可能需要检查脚本是否正确执行这些步骤,或者是否有权限问题。 用户的问题中提到的状态显示active但实际inactive,可能有两种情况:一种是服务确实启动成功但立即退出,另一种是服务类型配置不当导致状态显示不符。例如,如果使用Type=oneshot但期望服务持续运行,则状态会显示为inactive,而如果使用Type=simple但服务进程退出,则状态可能变为failed或inactive,但systemctl status可能显示为active (exited)。 接下来需要给出脚本的改进建议,包括: - 确保服务类型正确,例如对于需要持续运行的服务使用Type=simple或forking,并确保进程不退出的情况下保持运行。 - 添加正确的Restart策略,如on-failure,以便在服务异常退出时自动重启。 - 在脚本中添加服务状态检查,包括检查服务是否处于active (running)状态,而不仅仅是启动服务。 - 添加日志记录功能,方便用户查看服务运行情况,找出服务退出的原因。 - 在脚本中进行语法检查预验证,例如使用systemd-analyze verify来检查服务文件的正确性。 此外,需要处理用户提到的状态显示问题,可能需要检查服务状态的具体输出,例如使用systemctl is-activesystemctl status来确认服务的实际状态。 例如,如果服务类型为oneshot,那么服务启动后执行完命令就会变为inactive,这属于正常现象。但如果用户期望服务持续运行,则需要更改为其他类型,并确保ExecStart启动的进程持续运行,而不是立即退出。 另外,用户可能在脚本中正确配置了服务,但服务本身存在问题,例如依赖未满足、权限问题或路径错误。因此,脚本需要包含更多的错误检查日志记录,帮助用户诊断问题。 总结解决方案步骤: 1. 创建服务文件时确保Type正确,根据服务类型选择simple/forking/oneshot等。 2. 配置合适的Restart策略,确保服务异常退出时自动重启。 3. 在脚本中添加服务状态验证步骤,确认服务是否成功启动并保持active状态。 4. 添加日志记录功能,将服务日志输出到文件,便于排查问题。 5. 使用systemd-analyze verify检查服务文件的语法是否正确。 6. 处理可能的环境依赖问题,如网络、用户权限等。 通过以上步骤,可以解决服务状态显示实际不符的问题,并确保脚本能够正确配置启动服务。</think>根据系统服务状态管理机制引用内容[^1][^5],以下是完整的脚本解决方案及状态异常处理方法: ### 解决方案脚本(带状态验证) ```bash #!/bin/bash SERVICE_NAME="my_custom.service" SERVICE_PATH="/etc/systemd/system/$SERVICE_NAME" # 生成符合状态保持要求的服务文件 sudo tee $SERVICE_PATH > /dev/null <<EOF [Unit] Description=持久化自定义服务 After=network.target [Service] Type=simple # 适用于持续运行进程 ExecStart=/path/to/your/daemon --foreground # 必须保持前台运行 Restart=on-failure # 根据引用[5]配置异常重启 RestartSec=5s # 重启间隔 StandardOutput=syslog # 日志输出配置 StandardError=syslog [Install] WantedBy=multi-user.target EOF # 服务配置后操作 sudo systemctl daemon-reload sudo systemctl enable $SERVICE_NAME --now # 状态验证函数 check_service_status() { local status=$(systemctl is-active $SERVICE_NAME) local substate=$(systemctl show -p SubState $SERVICE_NAME | cut -d= -f2) if [[ "$status" == "active" && "$substate" == "running" ]]; then echo "√ 服务已正确运行 (active/running)" elif [[ "$status" == "active" && "$substate" == "exited" ]]; then echo "! 服务异常:进程已退出,检查Type类型或ExecStart命令" journalctl -u $SERVICE_NAME -n 20 --no-pager exit 1 else echo "× 服务启动失败,状态码: $status" systemctl status $SERVICE_NAME -l --no-pager exit 2 fi } # 延迟检测避免瞬时状态 sleep 2 check_service_status ``` ### 关键问题处理说明 1. **状态误判问题**: - 使用双重验证机制:`is-active`结合`SubState`字段检测 - 区分三种状态: - `active/running`:正常服务状态 - `active/exited`:进程异常退出(检查Type类型是否为oneshot) - `inactive`:服务未启动 2. **服务类型选择**: ```bash # 根据进程特性选择类型 Type=simple # 默认值,适用于立即启动且不退出的进程 Type=forking # 适用于需要后台守护进程 Type=oneshot # 单次任务执行(如清理脚本),配合RemainAfterExit=yes可实现伪激活状态 ``` 3. **日志追踪方法**: ```bash # 查看最近20条日志 journalctl -u your_service -n 20 -f # 持久化存储配置(引用[4]扩展) mkdir -p /var/log/my_service sudo tee -a $SERVICE_PATH > /dev/null <<'LOG' StandardOutput=append:/var/log/my_service.log StandardError=append:/var/log/my_service_error.log LOG ``` ### 高级调试技巧 1. **预验证服务配置**: ```bash systemd-analyze verify $SERVICE_PATH # 语法检查 systemd-analyze security $SERVICE_NAME # 安全策略分析 ``` 2. **环境变量注入**: ```ini [Service] Environment="DEBUG_MODE=1" ExecStart=/usr/bin/env /path/script.sh ``` 3. **依赖关系检查**: ```bash systemctl list-dependencies $SERVICE_NAME --reverse ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值