Skip to content

Oracle 连接控制与管理

连接控制是Oracle数据库安全与性能管理的核心组成部分,通过合理限制和管理数据库连接,可以防止资源耗尽、拒绝服务攻击和恶意连接,确保数据库资源的高效利用。对于DBA而言,掌握连接控制策略的配置、监控和优化是保障数据库稳定运行的关键。

连接控制核心概念

连接控制的主要维度

连接控制涉及以下几个关键维度:

  • 连接数限制:控制全局、用户或会话级别的最大连接数量
  • 连接超时:自动断开长时间空闲或未响应的连接
  • 连接来源:限制允许连接的IP地址或主机名
  • 连接资源:限制每个连接可使用的CPU、内存、I/O等资源
  • 连接认证:验证连接用户的身份和权限
  • 连接加密:保护连接数据的传输安全

连接相关的核心参数

参数名称功能描述默认值
PROCESSES数据库允许的最大进程数(包括连接进程)300
SESSIONS数据库允许的最大会话数PROCESSES * 1.1 + 5
TRANSACTIONS数据库允许的最大事务数SESSIONS * 1.1

连接数管理

全局连接数配置

查看当前连接状态

sql
-- 查看当前连接数统计
SELECT 
  COUNT(*) AS total_connections,
  SUM(CASE WHEN STATUS = 'ACTIVE' THEN 1 ELSE 0 END) AS active_connections,
  SUM(CASE WHEN STATUS = 'INACTIVE' THEN 1 ELSE 0 END) AS inactive_connections
FROM V$SESSION;

-- 查看每个用户的连接数
SELECT USERNAME, COUNT(*) AS connection_count
FROM V$SESSION
WHERE USERNAME IS NOT NULL
GROUP BY USERNAME
ORDER BY connection_count DESC;

-- 查看每个应用程序的连接数
SELECT PROGRAM, COUNT(*) AS connection_count
FROM V$SESSION
WHERE PROGRAM IS NOT NULL
GROUP BY PROGRAM
ORDER BY connection_count DESC;

-- 查看每个机器的连接数
SELECT MACHINE, COUNT(*) AS connection_count
FROM V$SESSION
WHERE MACHINE IS NOT NULL
GROUP BY MACHINE
ORDER BY connection_count DESC;

调整全局连接数

sql
-- 查看当前连接数参数
SELECT name, value
FROM V$PARAMETER
WHERE name IN ('processes', 'sessions', 'transactions');

-- 计算合适的连接数
-- 建议值:PROCESSES = CPU核心数 * 10-20(根据服务器配置调整)
-- SESSIONS = PROCESSES * 1.1 + 5
-- TRANSACTIONS = SESSIONS * 1.1

-- 修改连接数参数(需要重启数据库)
ALTER SYSTEM SET PROCESSES = 500 SCOPE = SPFILE;
ALTER SYSTEM SET SESSIONS = 555 SCOPE = SPFILE;
ALTER SYSTEM SET TRANSACTIONS = 610 SCOPE = SPFILE;

-- 重启数据库使参数生效
SHUTDOWN IMMEDIATE;
STARTUP;

用户级连接限制

使用Profile限制用户连接数

sql
-- 创建应用用户连接限制Profile
CREATE PROFILE app_user_profile LIMIT
  SESSIONS_PER_USER 10           -- 每个用户最大10个并发连接
  IDLE_TIME 60                    -- 空闲60分钟后断开
  CONNECT_TIME 1440;              -- 最大连接时长24小时

-- 创建管理员用户连接限制Profile
CREATE PROFILE admin_profile LIMIT
  SESSIONS_PER_USER 5             -- 管理员用户最大5个并发连接
  IDLE_TIME 30                    -- 空闲30分钟后断开
  CONNECT_TIME 720;               -- 最大连接时长12小时

-- 将Profile分配给用户
ALTER USER app_user PROFILE app_user_profile;
ALTER USER sysadmin PROFILE admin_profile;

-- 查看用户Profile配置
SELECT USERNAME, PROFILE
FROM DBA_USERS
WHERE USERNAME IN ('APP_USER', 'SYSADMIN');

监控用户连接数

sql
-- 查看用户当前连接数
SELECT USERNAME, COUNT(*) AS current_connections
FROM V$SESSION
WHERE USERNAME IS NOT NULL
GROUP BY USERNAME
HAVING COUNT(*) > 5;  -- 查找连接数超过5的用户

-- 查看用户连接历史趋势(需要AWR)
SELECT SNAP_ID, BEGIN_INTERVAL_TIME,
       MAX(ACTIVE_SESSIONS) AS max_active_sessions
FROM DBA_HIST_SYSMETRIC_SUMMARY
WHERE METRIC_NAME = 'Active Sessions'
GROUP BY SNAP_ID, BEGIN_INTERVAL_TIME
ORDER BY SNAP_ID;

连接超时管理

SQL*Net连接超时配置

服务端配置(sqlnet.ora)

# 启用TCP keepalive(建议启用)
TCP.KEEPALIVE = YES

# 空闲连接检测间隔(分钟)
SQLNET.EXPIRE_TIME = 15

# 入站连接超时(秒)
INBOUND_CONNECT_TIMEOUT = 30

# 出站连接超时(秒)
SQLNET.OUTBOUND_CONNECT_TIMEOUT = 30

# 连接建立超时(秒)
SQLNET.INBOUND_CONNECT_TIMEOUT_LISTENER = 60

监听器超时配置(listener.ora)

LISTENER = 
  (DESCRIPTION_LIST = 
    (DESCRIPTION = 
      (ADDRESS = (PROTOCOL = TCP)(HOST = db-server)(PORT = 1521))
    )
  )

# 监听器入站连接超时(秒)
INBOUND_CONNECT_TIMEOUT_LISTENER = 60

# 监听器响应超时(秒)
CONNECT_TIMEOUT_LISTENER = 10

Profile连接超时配置

sql
-- 创建超时限制Profile
CREATE PROFILE timeout_profile LIMIT
  IDLE_TIME 45                    -- 空闲45分钟后断开
  CONNECT_TIME 1080               -- 最大连接时长18小时
  IDLE_TIME 45                    -- 空闲45分钟后断开
  INACTIVE_ACCOUNT_TIME 365;       -- 账号365天不活动后锁定

-- 应用到用户
ALTER USER app_user PROFILE timeout_profile;

清理空闲连接

sql
-- 查找空闲时间超过1小时的会话
SELECT SID, SERIAL#, USERNAME, MACHINE, PROGRAM, 
       LAST_CALL_ET/60 AS idle_minutes
FROM V$SESSION
WHERE STATUS = 'INACTIVE' 
  AND LAST_CALL_ET > 60       -- 空闲超过1小时
  AND USERNAME IS NOT NULL
ORDER BY idle_minutes DESC;

-- 批量终止空闲会话(示例)
DECLARE
  CURSOR idle_sessions IS
    SELECT SID, SERIAL#
    FROM V$SESSION
    WHERE STATUS = 'INACTIVE' 
      AND LAST_CALL_ET > 3600  -- 空闲超过1小时
      AND USERNAME IS NOT NULL
      AND USERNAME != 'SYS';   -- 排除SYS用户
BEGIN
  FOR s IN idle_sessions LOOP
    EXECUTE IMMEDIATE 'ALTER SYSTEM KILL SESSION ''' || s.SID || ',' || s.SERIAL# || ''' IMMEDIATE';
    DBMS_OUTPUT.PUT_LINE('终止会话: ' || s.SID || ',' || s.SERIAL#);
  END LOOP;
END;
/

连接来源控制

SQL*Net节点检查

# 启用节点检查
TCP.VALIDNODE_CHECKING = YES

# 允许连接的IP地址/主机名列表
TCP.INVITED_NODES = (
  192.168.1.0/24,          # 允许整个网段
  10.0.0.10,              # 允许特定IP
  db-application-server    # 允许特定主机名
)

# 拒绝连接的IP地址/主机名列表
TCP.EXCLUDED_NODES = (
  192.168.1.100,          # 拒绝特定IP
  untrusted-host          # 拒绝特定主机名
)

防火墙连接控制

Linux iptables配置

bash
# 允许应用服务器网段访问数据库
iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 1521 -j ACCEPT

# 允许管理网段访问数据库
iptables -A INPUT -p tcp -s 10.0.0.0/24 --dport 1521 -j ACCEPT

# 拒绝其他所有IP访问数据库端口
iptables -A INPUT -p tcp --dport 1521 -j DROP

# 保存iptables规则
iptables-save > /etc/sysconfig/iptables

Windows防火墙配置

powershell
# 创建入站规则,允许特定IP访问1521端口
New-NetFirewallRule -DisplayName "Oracle Database Access" `
  -Direction Inbound `
  -Protocol TCP `
  -LocalPort 1521 `
  -RemoteAddress 192.168.1.0/24,10.0.0.0/24 `
  -Action Allow

连接资源限制

Profile资源限制配置

sql
-- 创建资源限制Profile
CREATE PROFILE resource_limit_profile LIMIT
  -- CPU资源限制
  CPU_PER_SESSION 1000000  -- 每个会话最多使用10秒CPU时间
  CPU_PER_CALL 100000      -- 每个调用最多使用1秒CPU时间
  
  -- 内存/IO资源限制
  LOGICAL_READS_PER_SESSION 1000000  -- 每个会话最多100万次逻辑读
  LOGICAL_READS_PER_CALL 100000      -- 每个调用最多10万次逻辑读
  
  -- 会话限制
  SESSIONS_PER_USER 10               -- 每个用户最多10个会话
  CONNECT_TIME 1440                  -- 每个会话最多24小时
  IDLE_TIME 60                       -- 空闲60分钟后断开
  
  -- 并发事务限制
  COMPOSITE_LIMIT 5000000;           -- 复合资源限制(CPU+I/O)

-- 启用资源限制
ALTER SYSTEM SET RESOURCE_LIMIT = TRUE SCOPE = BOTH;

-- 应用到用户
ALTER USER app_user PROFILE resource_limit_profile;

监控连接资源使用

sql
-- 查看会话资源使用情况
SELECT SID, SERIAL#, USERNAME, 
       CPU_TIME/100 AS cpu_seconds,  -- CPU使用时间(秒)
       BLOCK_GETS + CONSISTENT_GETS AS logical_reads,  -- 逻辑读数量
       PHYSICAL_READS AS physical_reads,  -- 物理读数量
       ROWS_PROCESSED  -- 处理的行数
FROM V$SESSION
WHERE USERNAME IS NOT NULL
ORDER BY cpu_seconds DESC;

-- 查看资源使用超过阈值的会话
SELECT SID, SERIAL#, USERNAME, CPU_TIME/100 AS cpu_seconds
FROM V$SESSION
WHERE CPU_TIME > 50000  -- CPU使用超过5秒
  AND USERNAME IS NOT NULL;

连接池管理

连接池类型与选择

Oracle数据库支持多种连接池技术:

连接池类型适用场景优势
Oracle UCPJava应用,需要高度可定制性官方支持,功能丰富,监控能力强
HikariCP性能要求高的Java应用轻量级,性能优异,配置简单
DBCP/C3P0传统Java应用稳定可靠,广泛使用
应用服务器连接池企业级应用,如WebLogic、WebSphere与应用服务器深度集成,管理方便
Oracle Database Resident Connection Pool (DRCP)短连接频繁的应用减少数据库进程开销,提高并发能力

Oracle DRCP配置

DRCP适合大量短连接的应用场景,可以显著减少数据库进程数量:

sql
-- 查看DRCP状态
SELECT NAME, STATUS FROM V$CPOOL_INFO;

-- 启用DRCP
EXEC DBMS_CONNECTION_POOL.START_POOL();

-- 配置DRCP
EXEC DBMS_CONNECTION_POOL.CONFIGURE_POOL(
  pool_name => 'SYS_DEFAULT_CONNECTION_POOL',
  minsize => 4,          -- 最小连接数
  maxsize => 40,         -- 最大连接数
  incrsize => 2,         -- 每次增加的连接数
  session_cached_cursors => 20,
  inactivity_timeout => 300,  -- 连接池空闲超时(秒)
  max_think_time => 60,       -- 会话最大思考时间(秒)
  max_use_session => 1000,     -- 每个会话最大使用次数
  max_lifetime_session => 3600 -- 会话最大生命周期(秒)
);

-- 查看DRCP配置
SELECT * FROM DBA_CPOOL_INFO;

UCP连接池配置示例

java
import oracle.ucp.jdbc.PoolDataSource;
import oracle.ucp.jdbc.PoolDataSourceFactory;

// 创建UCP数据源
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource();

// 基本配置
pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource");
pds.setURL("jdbc:oracle:thin:@//db-server:1521/PDB1");
pds.setUser("app_user");
pds.setPassword("SecurePass_2023");

// 连接池大小配置
pds.setInitialPoolSize(10);
pds.setMinPoolSize(5);
pds.setMaxPoolSize(50);

// 连接超时配置
pds.setConnectionWaitTimeout(30);          // 连接获取超时(秒)
pds.setInactiveConnectionTimeout(300);     // 空闲连接超时(秒)
pds.setAbandonedConnectionTimeout(1800);   // 废弃连接超时(秒)

// 连接验证配置
pds.setValidateConnectionOnBorrow(true);
pds.setSQLForValidateConnection("SELECT 1 FROM DUAL");
pds.setValidationTimeout(5);               // 连接验证超时(秒)

// 连接回收配置
pds.setConnectionHarvestMaxCount(10);       // 最大回收连接数
pds.setConnectionHarvestTriggerCount(40);   // 触发回收的连接数阈值

多租户环境连接管理

CDB与PDB连接控制

在多租户环境中,连接控制可以在CDB和PDB级别分别配置:

sql
-- CDB级别查看连接数
SELECT CON_ID, COUNT(*) AS connection_count
FROM V$SESSION
WHERE TYPE != 'BACKGROUND'
GROUP BY CON_ID
ORDER BY CON_ID;

-- 查看特定PDB的连接数
ALTER SESSION SET CONTAINER = PDB1;
SELECT COUNT(*) AS pdb1_connections
FROM V$SESSION
WHERE TYPE != 'BACKGROUND';

-- PDB级别设置资源限制
ALTER SESSION SET CONTAINER = PDB1;
CREATE PROFILE pdb1_app_profile LIMIT
  SESSIONS_PER_USER 15
  IDLE_TIME 45
  CONNECT_TIME 1080;

-- 为PDB用户分配Profile
ALTER USER pdb1_app_user PROFILE pdb1_app_profile;

多租户连接监控

sql
-- 查看所有PDB的连接数
SELECT
  P.PDB_NAME,
  COUNT(S.SID) AS connection_count
FROM
  CDB_PDBS P
LEFT JOIN
  V$SESSION S ON P.CON_ID = S.CON_ID AND S.TYPE != 'BACKGROUND'
GROUP BY
  P.PDB_NAME
ORDER BY
  connection_count DESC;

-- 查看PDB资源使用情况
SELECT
  P.PDB_NAME,
  S.CON_ID,
  COUNT(S.SID) AS sessions,
  SUM(S.CPU_TIME)/100 AS total_cpu_seconds,
  SUM(S.BLOCK_GETS + S.CONSISTENT_GETS) AS total_logical_reads
FROM
  CDB_PDBS P
JOIN
  V$SESSION S ON P.CON_ID = S.CON_ID
WHERE
  S.TYPE != 'BACKGROUND'
GROUP BY
  P.PDB_NAME, S.CON_ID
ORDER BY
  total_cpu_seconds DESC;

Oracle 19c与21c连接管理差异

特性Oracle 19cOracle 21c
DRCP增强基础DRCP支持增强的DRCP,支持自动伸缩和更细粒度监控
连接池监控基础UCP监控增强的UCP监控,提供实时连接池状态和性能指标
临时会话支持不支持支持临时会话,适合短期连接场景
连接加密TLS 1.2支持TLS 1.3,提供更强的加密保护
多租户连接PDB级连接限制增强的PDB连接管理,支持每个PDB独立的连接池
连接超时基础超时支持增强的超时配置,支持更细粒度的超时控制
连接溯源基础连接信息增强的连接溯源,提供更详细的连接元数据
自动连接管理支持自动调整连接数,根据负载动态伸缩

生产环境最佳实践

1. 连接数规划与配置

  • 根据硬件资源规划:PROCESSES参数建议设置为CPU核心数的10-20倍
  • 预留系统资源:为后台进程预留10-20%的PROCESSES额度
  • 分用户组配置:为不同类型用户(管理员、应用用户、只读用户)设置不同的连接限制
  • 启用资源限制:通过Profile限制每个用户的连接数和资源使用

2. 连接超时与回收

  • 配置合理的超时时间
    • 应用用户:IDLE_TIME = 60分钟,CONNECT_TIME = 24小时
    • 管理员用户:IDLE_TIME = 30分钟,CONNECT_TIME = 12小时
  • 启用SQL*Net检测:SQLNET.EXPIRE_TIME = 15分钟
  • 定期清理空闲连接:使用脚本或工具定期清理长时间空闲的连接
  • 监控连接超时事件:通过审计或日志监控连接超时情况

3. 连接来源控制

  • 限制连接IP范围:只允许应用服务器、管理终端等必要IP连接
  • 结合防火墙使用:同时使用SQL*Net节点检查和操作系统防火墙
  • 定期审查允许列表:每季度审查一次允许连接的IP列表
  • 记录连接来源:启用审计记录所有连接的来源信息

4. 连接池优化

  • 选择合适的连接池类型:根据应用特点选择UCP、HikariCP或DRCP
  • 配置合理的池大小
    • 初始池大小 = 平均并发连接数
    • 最大池大小 = 峰值并发连接数
    • 最小池大小 = 初始池大小的50%
  • 启用连接验证:设置validateConnectionOnBorrow = true
  • 配置合理的超时参数:连接获取超时、空闲超时、废弃超时

5. 监控与告警

  • 监控连接数趋势:通过AWR或第三方工具监控连接数变化趋势
  • 设置连接数告警:当连接数超过阈值(如PROCESSES的80%)时发送告警
  • 监控异常连接:监控连接数突增、长时间运行的会话、资源消耗异常的会话
  • 审计连接事件:启用统一审计记录连接建立、断开、授权等事件

常见问题(FAQ)

Q:如何快速查看数据库当前连接数?

A:可以使用以下SQL查询:

sql
SELECT COUNT(*) AS total_connections,
       SUM(CASE WHEN STATUS = 'ACTIVE' THEN 1 ELSE 0 END) AS active_connections
FROM V$SESSION;

Q:如何处理数据库连接数满的情况?

A:处理步骤:

  1. 查看当前连接状态,识别异常连接
  2. 终止空闲时间过长的连接
  3. 检查是否有连接泄漏(应用未正确关闭连接)
  4. 考虑临时增加PROCESSES参数
  5. 长期解决方案:优化应用连接池配置,增加数据库硬件资源

Q:如何限制特定IP的连接数?

A:可以通过以下方法:

  1. 使用SQL*Net的TCP.INVITED_NODES限制允许连接的IP
  2. 结合防火墙规则限制IP访问
  3. 使用数据库触发器在连接时检查IP并限制连接数

Q:DRCP和传统连接池有什么区别?

A:DRCP(Database Resident Connection Pool)是数据库端的连接池,而传统连接池是应用端的连接池。DRCP适合大量短连接场景,可以减少数据库进程数量,降低内存消耗,提高并发能力。

Q:如何监控连接池的使用情况?

A:对于UCP连接池,可以使用UCP监控API或Oracle Enterprise Manager;对于HikariCP,可以通过其内置的监控指标或集成Prometheus/Grafana;对于DRCP,可以查询V$CPOOL*视图。

Q:Oracle 21c的临时会话有什么用途?

A:临时会话是Oracle 21c的新特性,适合短期连接场景,会话结束后资源会被自动回收,无需手动清理,有助于提高资源利用率和减少管理开销。

Q:如何优化应用连接池配置?

A:优化建议:

  1. 根据应用负载调整池大小
  2. 设置合理的超时参数
  3. 启用连接验证
  4. 配置连接回收机制
  5. 监控连接池指标,如连接等待时间、连接使用率等
  6. 考虑使用DRCP处理大量短连接

Q:如何防止连接泄漏?

A:防止连接泄漏的方法:

  1. 确保应用程序正确关闭连接(使用try-with-resources或finally块)
  2. 配置连接池的废弃连接超时
  3. 监控连接池的连接使用时间
  4. 定期检查长时间运行的会话
  5. 使用连接池的连接泄漏检测功能

总结

连接控制是Oracle数据库管理的核心内容,合理的连接管理策略可以有效保障数据库的安全性、可用性和性能。DBA需要根据数据库的硬件资源、应用特点和业务需求,配置适当的连接数限制、超时参数、资源限制和连接池设置。

随着Oracle版本的演进,连接管理功能不断增强,特别是Oracle 21c引入的临时会话、增强的DRCP和多租户连接管理等特性,为DBA提供了更强大的连接管理能力。通过结合监控工具和自动化脚本,DBA可以实现连接的精细化管理,确保数据库资源的高效利用,防止资源耗尽和安全威胁。

定期审查连接配置、监控连接状态、优化连接池设置是DBA日常工作的重要组成部分,也是保障数据库稳定运行的关键措施。