zoukankan      html  css  js  c++  java
  • (转)ORACLE中SID和SERVICE_NAME的区别

    背景:之前一直分不清plsql和程序中配置文件url之间的连接,想当然的认为service_name 和jdburl后面的实例相对应,直到出错的这一天,通过这篇博客,彻底扫除了盲点。

    1 问题

    1.1 问题描述

    plsql的tnsnames.org中的数据源是这么配置的

    应用程序中的配置文件是这么配置的:

    启动程序,报错:

    Caused by: oracle.net.ns.NetException: Listener refused the connection with the following error:
    ORA-12505, TNS:listener does not currently know of SID given in connect descriptor

     这里我只是单纯的将 “”:“” 后面的名称和service_name 对应上去,完全是想当然的做法。

    1.2 问题解决

    这个问题同事首先给我的解决方案是,将url后面的sjjdb 改为sjjdb1,这个不是数据库的实例名吗,我虽然不相信,但是改完后确实能够正常启动程序,百思不得其解啊。

    于是,我在网上找到了查看数据库sid_name 的方法

    例如:jdbc:oracle:thin:@192.168.0.58:1521:ORCL
    最后的ORCL就是sid_name

    附:
    察看数据库中当前的sid的方法:

    SQL> select INSTANCE_NAME from v$instance;

    INSTANCE_NAME

    ----------------
    hasl

    然后,我就在plsql中执行了一遍命令,发现:

    我擦,我的sid_name 居然是sjjdb2,我去修改程序中的配置文件为connection.url=jdbc:oracle:thin:@168.33.131.19:1521:sjjdb2  

    非常6,程序跑起来了。这时候我在想,sid_name和service_name之间到底是个什么关系呢?

    于是就有了第二章的终极解决方案,茅塞顿开的感觉!

    2 彻底明白sid_name和service_name之间的区别

    2.1 顿悟

    ps:RAC,全称real application clusters,译为“实时应用集群”, 是Oracle新版数据库中采用的一项新技术,是高可用性的一种,也是Oracle数据库支持网格计算环境的核心技术。

    先来讲一个小故事,2015年6月份,有个客户迁移了数据库,由单实例数据库变成了RAC。Java应用程序出现了无法连接数据库的情况,但是PL/SQL能连接上数据库(我就是的)。

    由于项目比较庞大,虽然在半夜切换的,但是也不能接受长时间的业务停顿。当时,我对Oracle技术也只是略知皮毛。在咨询过公司研发后,他们给我的建议是:

    参考PL/SQL的连接参数,将spring中jdbc连接的url由jdbc:oracle:thin:@10.2.0.2:1521:orcl改为jdbc:oracle:thin:@(DESCRIPTION =(ADDRESS_LIST =(ADDRESS =(PROTOCOL = TCP)(HOST = 10.2.0.2)(PORT = 1521)))(CONNECT_DATA =(SERVICE_NAME = orcl))),结果问题解决了,当时我挺佩服公司研发的。

    现在看来,这个并不是最佳的解决方案,下面通过讲解SID和SERVICE_NAME的区别,我将给出更佳的解决方案。

            在讲解SID和SERVICE_NAME之前,先说一下实例。实例是操作系统中访问数据库所需要的一系列的进程和内存的集合。即使没有任何数据文件,实例也可以启动。但是要想访问数据库,必须把数据库文件加载进实例中。

    实例和数据库的区别可以简单概括为:实例是临时的,它只在相关的进程和内存集合存在时存在,而数据库是永久的,只要文件存在它就存在。一个实例只能对应一个数据库,但是一个数据库可以由多个实例对应(如RAC)。RAC就是多个实例同时打开一个数据库文件的系统,在结构上是多台机器,每台机器运行一个实例,每个实例都打开同一个数据库 (这个是用磁盘共享技术实现的),这些实例之间需要同步高速缓存,这样保证多个实例是完全一致的,不会相互冲突乃至覆盖。

           SID即INSTANCE_NAME是用来唯一标示实例的。SERVICE_NAME是oracle8i新引进的,8i之前,一个数据库只能由一个实例对应,但是随着高性能的需求,并行技术的使用,一个数据库可以由多个实例对应了,比较典型的应用如RAC。为了充分利用所有实例,并且令客户端连接配置简单,ORACLE提出了SERVICE_NAME的概念。该参数直接对应数据库,而不是某个实例。

          了解了SID和SERVICE_NAME之后,我突然觉得前面故事中使用的解决方案并不是最佳的解决方案,因为SERVICE_NAME的出现就是为了应对并发技术,简化客户端连接配置。通过SERVICE_NAME应该能找到更好的解决方案。通过查找JDBC帮助得知JDBC连接ORACLE的方法由三种:

    格式一:jdbc:oracle:thin:@//<host>:<port>/<service_name>
    格式二:jdbc:oracle:thin:@<host>:<port>:<SID> 
    格式三:jdbc:oracle:thin:@<TNSName> 

           不难看出,故事中使用RAC之前,JDBC是使用格式二连接的,使用RAC后实例增多了,SID已经不唯一,格式二已经无法完全利用所有资源。研发参考PL/SQL的连接方法刚好碰巧使用了格式三。(这不是直接将数据源搞上去吗,low啊)因为java应用服务器跟数据库服务器是分离的,应用服务器上没有oracle的服务端以及客户端。虽然解决方案中没有使用TNSName,但是使用了TNSName的连接描述,效果是一样的。既然JDBC有三种连接方案,我们不妨再看一下第一种方案。

    再加上前面的讲解内容,我想大家已经都知道故事中的问题该怎么修改了,只要改成jdbc:oracle:thin:@//10.2.0.2:1521/orcl就可以了,而且这种格式也支持单实例数据库。这也是ORACLE在8i之后增加SERVICE_NAME的初衷。

           通过这个故事,我们可以看到,只有充分了解了ORACLE的知识,才能更好的使用ORACLE技术。

    so,最后的的问题解决方案就是通过加 /解决的:

    connection.url=jdbc:oracle:thin:@168.33.131.19:1521/sjjdb

     2.2 引申

    oracle中的service_name 是什么?

  • 相关阅读:
    在MS Sql Server中可以能过以下的方法查询出磁盘空间的使用情况及各数据库数据文件及日志文件的大小及使用利用率:
    sqlserver日志的备份与还原
    C#中String 与Color之间的相互转换
    sql 替换字符串
    Components_Box
    射线检测与碰撞通道设置
    切碎方块
    音乐可视化
    枚举
    UI与Actor(蓝图)的互动
  • 原文地址:https://www.cnblogs.com/lixuwu/p/7127148.html
Copyright © 2011-2022 走看看