问题:
kettle连接Oracle时候报错:
错误连接数据库 [MFG Prod] : org.pentaho.di.core.exception.KettleDatabaseException:
Error occurred while trying to connect to the database
Error connecting to database: (using class oracle.jdbc.driver.OracleDriver)
Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
org.pentaho.di.core.exception.KettleDatabaseException:
Error occurred while trying to connect to the database
Error connecting to database: (using class oracle.jdbc.driver.OracleDriver)
Listener refused the connection with the following error:
ORA-12505, TNS:listener does not currently know of SID given in connect descriptor
排查一:
连接另外一个Oracle数据库都是正常的,经过查询两个Oracle的版本不一致,可能是oracle jar包版本的问题于是像这位前辈学习了一下:
Oracle数据库的驱动包ojdbc*.jar之间的差别 - elleniou - 博客园
尽量使用和数据库版本一致的驱动,有bug时,换高版本的JDBC驱动试试 。
换成对应的jar包还是报错,排除jar不兼容问题。
排查二:
最后查到的原因如下
查找资料得知:
jdbc连接数据库的时候,需要使用数据库的sid_name,而不是数据库的services_name
而使用plsql连接数据库的时候,只需要数据库的services_name即可,所以修改连接字符串中的services_name (即连接参数中的database name)为sid_name。
现在很多工具提供了两种连接方式,例如dbeaver
因为这个工具是java写的,底层还是jdbc,应该也是会转化为下面的方式去连接。
通过查找JDBC帮助得知JDBC连接ORACLE的方法由三种: 格式一:jdbc:oracle:thin:@//<host>:<port>/<service_name> 格式二:jdbc:oracle:thin:@<host>:<port>:<SID> 格式三:jdbc:oracle:thin:@<TNSName>
jdbc连接oracle的方式
# jdbc连接oracle实例 driverClassName: oracle.jdbc.driver.OracleDriver url: jdbc:oracle:thin:@10.2.1.22:1521:testdb1 username: abc password: 123
# jdbc连接oracle service_name driverClassName: oracle.jdbc.driver.OracleDriver url: jdbc:oracle:thin:@10.2.1.5:1521/PRODDB username: adm password: admin
在操作系统中要取得与数据库之间的交互,必须使用数据库实例名。例如,要和某一个数据库server连接,就必须知道其数据库实例名,只知道数据库名是没有用的,与数据库名不同,在数据安装或创建数据库之后,实例名可以被修改。
那么sid_name 和service_name 到底有什么区别?
1.数据库实例名(SID)
什么是数据库实例名?
数据库实例名是用于和操作系统进行联系的标识,就是说数据库和操作系统之间的交互用的是数据库实例名。实例名也被写入参数文件中,该参数为instance_name,在win平台中,实例名同时也被写入注册表。
数据库名和实例名可以相同也可以不同。
在一般情况下,数据库名和实例名是一对一的关系,但如果在oracle并行服务器架构(即oracle实时应用集群)中,数据库名和实例名是一对多的关系。(MFG的PROD是如此,最著名的是如RAC技术)
一个serice name 对应多个 sid name.
2.数据库服务名(SERVICE_NAME)
什么是数据库服务名?
从oracle9i版本开始,引入了一个新的参数,即数据库服务名。参数名是SERVICE_NAME。
如果数据库有域名,则数据库服务名就是全局数据库名;否则,数据库服务名与数据库名相同。
tnsname.ora 如下
配置tnsname.ora时,可以用SID,也可以用SERVICE_NAME. 注意这两个值不一定相同,具体要看数据库服务器中的配置。
connect_data对应的是SID还是SERVICE_NAME? 如果是SID则对应该数据库的实例名称(instant_name),如果是SERVICE_NAME的话则填写数据库服务名,即全局数据库名
PS:查看数据库的sid_name语句:
select INSTANCE_NAME from v$instance;
总之jdbc连接数据库的时候是sid_name;
psql连接数据库的时候是service_name;
我们平常使用工具连接的都属于psql连接,kettle是通过java jdbc接口连接DB的,故应该为sid_name,事实上,多数的数据库两者一致,导致我们忽视了此问题。
参考文章:ORACLE中SID和SERVICE_NAME的区别 - lclc - 博客园