Oracle 19c Kerberos认证下UCP初始化池大小>2触发ORA-12631异常求助
Linux环境部署Oracle 19c,通过Windows AD KDC启用Kerberos认证后,sqlplus与JDBC直接访问均正常。但使用ucp11.jar、ojdbc11.jar连接池时,仅当initialPoolSize>2时,调用pds.getConnection()会抛出ORA-12631异常。
测试代码
PoolDataSource pds = PoolDataSourceFactory.getPoolDataSource(); pds.setConnectionFactoryClassName("oracle.jdbc.pool.OracleDataSource"); pds.set(url); pds.setUser(null); // Kerberos认证无需显式用户密码 pds.setPassword(null); pds.setInitializePoolSize(3); // 设置为3及以上时触发ORA-12631 pds.setMinPoolSize(3); pds.setMaxPoolSize(20); pds.setTimeoutCheckInterval(120); pds.setInactiveConnectionTimeout(300); pds.setConnectionProperties(krbProperties); // 包含KRB5_CC_NAME等Kerberos配置
关键现象
initialPoolSize设为1或2时,可正常获取连接并执行查询- 关闭Kerberos认证后,无论池大小设置多少,连接池均能正常运行
用户疑问
- 为何初始化池大小大于2时会触发该异常?
- Kerberos认证无需用户/密码,为何会抛出ORA-12631?
ORA-12631的本质
ORA-12631是Oracle的「用户名检索失败」错误,虽然Kerberos不需要显式输入用户名密码,但JDBC驱动仍需从Kerberos票据(Ticket)中提取有效用户身份信息,或通过配置属性获取凭证。这个错误本质是无法获取合法的身份凭证,而非缺少显式的账号密码。
初始化池大小>2时异常的核心原因
UCP初始化连接池时,默认会并行创建多个连接。而Kerberos的票据缓存(CCACHE)存在并发访问限制:
- 单个CCACHE文件同一时间只能被一个线程读取/写入
- 当UCP并发创建第3个及以上连接时,多个线程同时争抢访问同一个
KRB5_CC_NAME指定的缓存文件,导致凭证读取失败,触发ORA-12631
验证与解决方法
使用线程独立的Kerberos凭证
避免多线程共享同一个CCACHE文件,可配置每个线程使用独立的内存缓存或临时文件缓存。例如在krbProperties中添加:java.security.auth.login.config=/path/to/jaas.conf sun.security.krb5.debug=true # 开启调试便于排查凭证问题同时在JAAS配置中指定
com.sun.security.auth.module.Krb5LoginModule,设置useTicketCache=true和renewTGT=true,确保每个线程能获取独立的有效凭证。将UCP连接创建改为串行模式
通过UCP配置让连接池初始化时串行创建连接,避免并发访问CCACHE冲突。例如添加:pds.setConnectionCreationRetryAttempts(3); pds.setConnectionCreationRetryFrequency(1000);或者自定义
OracleDataSource包装类,在创建连接时加锁,保证同一时间只有一个线程访问Kerberos凭证。检查Kerberos票据的有效性
确认当前使用的Kerberos票据有效期足够,且运行应用的系统用户对CCACHE文件有读写权限。票据过期时,并发创建连接更容易出现凭证读取失败。
为何关闭Kerberos后无异常
关闭Kerberos后,JDBC会 fallback 到普通数据库认证逻辑(即使user/password设为null,也可能依赖操作系统身份或其他默认认证方式),此时不存在多线程共享凭证缓存的冲突问题,因此无论池大小多少都能正常运行。
内容的提问来源于stack exchange,提问作者Joel

