sqlplus 安装

Oracle数据库软件十分庞大,数据库引擎有好几个G。通常情况下,我们的使用方式是安装一个Oracle数据库在服务器机器上,在客户端通过PL/SQL Developer、sqlplus等工具操作服务器上的数据,当然Oracle 10g后,OEM(企业管理器)已经是WEB版了,在浏览器中也可以同样操作数据库。

Windows 下Oracle Instant Client 的安装

Windows下客户端工具 PL/SQL Developer 使用得最多,Linux下,我喜欢直接使用sqlplus。不论使用哪种工具,都需要在客户端机器上安装Oracle客户端工具,安装以下三种软件均可连接Oracle服务器:

  • Oracle 数据库引擎
  • Oracle Client
  • Oracle Instant Client

其中前两种占硬盘空间大,并且安装也相对繁琐,我一般喜欢采用第三种方式,因此,下面介绍 Oracle Instant Client 的安装:

  1. Windows 下Oracle Instant Client 的安装

  2. Oracle Instant Client 下载

    • 进入Oracle官网首页,单击首页中的downloads链接,在新页面中选择 Database —> Instant Client,进入 Instant Client Downloads 页,选择相应版本下载。
    • Oracle 中文网站
    • 我下载的软件包是:basic、sqlplus.
    • 注意,必须下载basic或者basiclite其中之一,若需要做 OCI / OCCI 开发,还需下载 sdk.
  3. Oracle Instant Client 安装

    • 安装很简单,只需直接解压两个包即可,将两个包解压到同一目录下
    • 例如解压到目录 D:\instantclient-10.2.0.3-win32\下。
    • 最后目录结构是:D:\instantclient-10.2.0.3-win32\instantclient_10_2instantclient_10_2目录下就是解压后的 basicsqlplus.
  4. 创建数据库连接文件
    D:\instantclient-10.2.0.3-win32\instantclient_10_2 目录下创建文件夹 admin,在 admin 目录下创建文件 tnsnames.ora,根据数据库连接输入以下类似内容

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # tnsnames.ora Network Configuration File: /opt/oracle_11g_R2_x64/product/11.2.0.1.0/db_1/network/admin/tnsnames.ora
    # Generated by Oracle configuration tools.

    ORCL =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.232.133)(PORT = 1521))
    (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = orcl)
    )
    )

    该文件和数据库服务器中的文件内容类似,其作用是配置 sqlplus 和 PL/SQL Developer 中连接时的连接字符串。大家都知道该文件的作用,不必赘述。

  5. 配置Windows环境变量

1
2
3
4
5
ORACLE_HOME=D:\instantclient-10.2.0.3-win32\instantclient_10_2

Path=%ORACLE_HOME%; xxxxxx ===> 作用是在命令行中可以找到 sqlplus 等命令,在运行sqlplus时加载相关库
TNS_ADMIN=%ORACLE_HOME%\admin ===> 作用是在sqlplus等工具中连接数据库时能找到 tnsnames.ora中的连接符
NLS_lANG=SIMPLIFIED CHINESE_CHINA.ZHS16GBK ===> 设置客户端的字符集
  1. 完成,测试!

    经过以上步骤后,Oracle Instant Client 安装完毕,在命令行中可以使用命令连接服务器.

1
2
3
4
5
6
7
C:\Users\kebyn>sqlplus /nolog

SQL*Plus: Release 10.2.0.3.0 - Production on 星期二 1月 10 10:52:53 2012

Copyright (c) 1982, 2006, Oracle. All Rights Reserved.

SQL> conn scott/tiger@orcl ===> 使用到 %TNS_ADMIN% 下 tnsnames.ora中的连接符ORCL

Linux 下 Oracle Instant Client 的安装

  1. 下载

Linux 下的 Oracle Instant Client有rpm包和zip包两种,下载任意一种即可,这里以下载的 zip包为例

1
2
3
4
5
oracle-instantclient11.2-basic-11.2.0.1.0-1.x86_64.zip

oracle-instantclient11.2-sqlplus-11.2.0.1.0-1.x86_64.zip

oracle-instantclient11.2-sdk-11.2.0.1.0-1.x86_64.zip
  1. 解压安装
    文件被解压到目录 instantclient_11_2 下
  2. 创建数据库连接文件
    1
    2
    3
    cd instantclient_11_2
    mkdir network/admin
    vim network/admin/tnsnames.ora
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # tnsnames.ora Network Configuration File: /sdb1/oracle/11gR2_database_X64/product/11.2.0.1.0/db_1/network/admin/tnsnames.ora
    # Generated by Oracle configuration tools.

    ZKL =
    (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = glnode04)(PORT = 1521))
    (CONNECT_DATA =
    (SERVER = DEDICATED)
    (SERVICE_NAME = zkl)
    )
    )
  3. 配置环境变量
    1
    vim ~/.bashrc
    1
    2
    3
    4
    5
    export ORACLE_HOME=/root/linux-11.2.0.1.0-1.x86_64/instantclient_11_2
    export PATH=$ORACLE_HOME:$PATH
    export TNS_ADMIN=$ORACLE_HOME/network/admin
    export LD_LIBRARY_PATH=$ORACLE_HOME:$LD_LIBRARY_PATH
    export NLS_LANG='simplified chinese_china.ZHS16GBK'
    注意要配置LD_LIBRARY_PATH 变量,sqlplus等程序运行时需要加载相应库,若不配置,则运行时会出现如下错误:
    1
    2
    3
    Error 6 initializing SQL*Plus
    SP2-0667: Message file sp1<lang>.msb not found
    SP2-0750: You may need to set ORACLE_HOME to your Oracle software directory
    配置完毕后
    1
    source  ~/.bashrc
  4. 完成,测试!
    1
    2
    3
    4
    5
    6
    7
    8
    9
    [root@kebyn instantclient_11_2]# sqlplus /nolog

    SQL*Plus: Release 11.2.0.1.0 Production on 星期二 1月 10 11:14:31 2012

    Copyright (c) 1982, 2009, Oracle. All rights reserved.

    SQL> conn zkl/zkl@zkl
    已连接。
    SQL>

在Oracle中,我们会遇到下面一系列的十分重要的参数。同时他们的含义也常常让我们混淆。这些参数有:
ORACLE_SID, SID, INSTANCE_NAME, SERVICE_NAME, SERVICES_NAMES, DB_NAME, GLOBAL_DBNAME, SID_NAME,以及网络服务名(net service name),实例服务名(instance service name)等。

  1. ORACLE_SIDSIDINSTANCE_NAME 以及 SID_NAME
    ORACLE_SID:即ORACLE System IDentifier,它是一个环境变量。
    我们一般在oracle用户的home目录中的.bash_profile中进行定义,一般该文件包含下面一行:
    1
    2
    grep ORACLE_SID .bash_profile
    export ORACLE_SID=orcl
    其作用就是:
    在我们使用在sqlplus工具中startup启动数据库时,OS就是利用这个环境变量来fork创建构成Oracle实例的各个进程,以及来命名一些文件的名字。

下面的命令的执行必须要有环境变量ORACLE_SID:

1
SQL> startup

那么我们的环境变量ORACLE_SID应该设置成什么值呢?
应该是:我们想要startup哪个Oracle实例,就应该将ORACLE_SID设置成哪个实例的SID:
Oracle server由Oracle实例和Oracle数据库两者共同组成。

  1. 很显然地,我们想要startup哪个Oracle实例,就应该将环境变量ORACLE_SID设置成哪个SID。
  2. SID唯一地标识一个Oracle实例,而ORACLE_SID启动该实例,启动之后我们得到一个Oracle实例,这个实例有一个名字:INSTANCE_NAMESID==>>ORACLE_SID==>>INSTANCE_NAME这三者是一致的,是完全相同的
  3. 同时这个实例向外提供服务,所以又有一个SERVICE_NAME

SID_NAME出现在lisnter.ora文件中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
[oracle@localhost oracle]$ cat listener.ora
# listener.ora Network Configuration File: /u01/app/oracle/product/10.2.0/db_1/network/admin/listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = PL***tProc)
(ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1)
(PROGRAM = extproc)
)
(SID_DESC =
(SID_NAME = orcl)
(ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1)
(GLOBAL_DBNAME = orcl)
)
)

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
)

lisnter.ora中的SID_NAME的值必须与SID的值一致。通过lisnter.ora中的SID_NAME和GLOBAL_DBNAME两个参数以及客户端的tnsnames.ora中的SERVICE_NAME,这三个参数一起作用,可以实现ORACLE客户端与服务端的隔离。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
[oracle@localhost oracle]$ cat tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/10.2.0/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

JIAGULUN =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = orcl)
)
)

EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
)
(CONNECT_DATA =
(SID = PL***tProc)
(PRESENTATION = RO)
)
)

客户端根据tnsname.ora中的SERVICE_NAME和地址(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521)),到这个地址去访问监听器。然后监听器根据文件lisnter.ora文件中的GLOBAL_NAME来判断是否有一个 GLOBAL_DBNAME 和 SERVICE_NAME 相等。如果相等,则建立客户端到SID标识的服务端实例的连接。(有一个例外:tnsnames.ora中可以用参数SID来取代SERVICE_NAME,这时比较的是tnsnames.ora中的SID和lisnter.ora中的SID_NAME,但是从oracle9i开始不推荐使用SID。因为SID无法隔离客户端和服务端)

tnsnames.ora中的地址(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))是监听器监听的地址。监听器进程一直在这个地址上监听,等待客户端的连接。

总结一下:

  1. 客户端和服务端的隔离是通过lisnter.ora中的GLOBAL_DBNAME来实现的,GLOBAL_DBNAME是一个连接客户端和服务端的桥梁:
    a>client端tnsnames.ora中的SERVICE_NAME和server端lisnter.ora中的GLOBAL_DBNAME相等;
    b>server端的lisnter.ora中的SID_NAME与系统的SID相等;
  2. SID==>>SID_NAME==>>ORACLE_SID==>>INSTANCE_NAME 四者是一致的,相等的;
  3. 可以在lisnter.ora中配置多个不同的GLOBAL_NAME来供不同的客户端SERVICE_NAME来对应,从而实现不同的客户端使用不同的SERVICE_NAME来访问同一个SID实例使用,配置如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    lisnter.ora:
    (SID_DESC =
    (SID_NAME = jiagulun)
    (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1)
    (GLOBAL_DBNAME = jiagulun)
    )
    (SID_DESC =
    (SID_NAME = jiagulun)
    (ORACLE_HOME = /u01/app/oracle/product/10.2.0/db_1)
    (GLOBAL_DBNAME = jgl)
    )

    tnsnames.ora:
    JIAGULUN =
    (DESCRIPTION =
    (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
    )
    (CONNECT_DATA =
    (SERVICE_NAME = jiagulun)
    )
    )

    JGL =
    (DESCRIPTION =
    (ADDRESS_LIST =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
    )
    (CONNECT_DATA =
    (SERVICE_NAME = jgl)
    )
    )
    同时设置一下参数service_names(不进行该项设置似乎也可以,无关紧要)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    SQL> show parameter service
    NAME TYPE VALUE
    ------------------------------------ ----------- ------------------------------
    service_names string jiagulun
    SQL> alter system set service_names = 'jiagulun,jgl' scope=both;
    System altered.
    SQL> show parameter service
    NAME TYPE VALUE
    ------------------------------------ ----------- ------------------------------
    service_names string jiagulun,jgl
    SQL>

测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[oracle@redhat4 admin]$ tnsping jiagulun
TNS Ping Utility for Linux: Version 10.2.0.1.0 - Production on 01-NOV-2012 20:12:22
Copyright (c) 1997, 2005, Oracle. All rights reserved.
Used parameter files:
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = jiagulun)))
OK (0 msec)

[oracle@redhat4 admin]$ tnsping jgl
TNS Ping Utility for Linux: Version 10.2.0.1.0 - Production on 01-NOV-2012 20:12:27
Copyright (c) 1997, 2005, Oracle. All rights reserved.
Used parameter files:
Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = jgl)))
OK (10 msec)
[oracle@redhat4 admin]$

现在我们在客户端既可以使用SERVICE_NAME=jiagulun来访问服务端,也可以使用SERVICE_NAME=jgl来访问。使用plsql develop用jgl和jiagulun都可以正常登陆。

  1. SID 与 DB_NAME
    显然,DB_NAME唯一性地标识了 oracle database,与数据库物理文件相关;而SID唯一性地标识了oracle instance,与所有进程相关。而oracle database和oracle instance一起组成了oracle server. SID和DB_NAME在非RAC环境默认是相等的。但是二者相等与否,无关紧要。在RAC环境,因为一个DB_NAME对应多个SID,所以不可能相等了。

DB_NAME是最重要的一个参数,在dbca中填写的DB_NAME,应该与启动参数文件pfile/spfile中的一致。在dbca中创建数据库时填写DB_NAME被写入到了多个地方:启动参数文件、控制文件、数据文件、日志文件等。
所以我们不能随便地修改启动参数文件中的DB_NAME参数:

1
2
3
4
5
6
7
8
9
sys@JIAGULUN> create pfile from spfile;
File created.

sys@JIAGULUN> exit
Disconnected from Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
[oracle@redhat4 oradata]$ grep db_name /u01/app/oracle/product/10.2.0/db_1/dbs/initjiagulun.ora
*.db_name='jiagulun'
[oracle@redhat4 oradata]$

如果启动参数文件中的DB_NAME与控制文件中的不一致,则在mount阶段会报错。

  1. SERVICE_NAME 与 SERVICE_NAMES
    SERVICE_NAME是Oracle实例提供的服务名。它隔离了Oracle实例,客户端仅仅需要知道SERVICE_NAME就可以访问实例。而不需要知道实例的SID。更不需要知道DB_NAME等信息。
    SERVICE_NAMES为实例定义一个或多个SERVICE_NAME,这样可以通过多个SERVICE_NAME将不同的用户连接区分开来。

service name似乎应该分为两种,一种是实例服务名 instance service name,一种是网络服务名 net service name,如下tnsnames.ora所示:

1
2
3
4
5
6
7
8
9
net_service_name =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = instance_service_name)
)
)

而plsql develop登陆使用的是net_service_name,而不是instance_service_name。
而tnsping 测试的也是net_service_name,而不是instance_service_name。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
[oracle@redhat4 admin]$ cat tnsnames.ora
# tnsnames.ora Network Configuration File: /u01/app/oracle/product/10.2.0/db_1/network/admin/tnsnames.ora
# Generated by Oracle configuration tools.

JIAGULUN =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = jiagulun)
)
)

net_jgl =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))
)
(CONNECT_DATA =
(SERVICE_NAME = jgl)
)
)

EXTPROC_CONNECTION_DATA =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC0))
)
(CONNECT_DATA =
(SID = PL***tProc)
(PRESENTATION = RO)
)
)

[oracle@redhat4 admin]$ tnsping net_jgl
TNS Ping Utility for Linux: Version 10.2.0.1.0 - Production on 02-NOV-2012 14:01:55
Copyright (c) 1997, 2005, Oracle. All rights reserved.
Used parameter files:

Used TNSNAMES adapter to resolve the alias
Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.0.100)(PORT = 1521))) (CONNECT_DATA = (SERVICE_NAME = jgl)))
OK (10 msec)
[oracle@redhat4 admin]$ tnsping jgl
TNS Ping Utility for Linux: Version 10.2.0.1.0 - Production on 02-NOV-2012 14:01:59
Copyright (c) 1997, 2005, Oracle. All rights reserved.
Used parameter files:
TNS-03505: Failed to resolve name
[oracle@redhat4 admin]$

如上所示:当我们使用 tnsping instance_service_name是失败了。
而 sqlplus scott/tiger@net_jgl 使用的也是net_service_name.

所以 tnsping, sqlplus user/passwd@net_jgl, plsql develop使用的都是net_service_name,而不是instance_service_name.

1
2
3
4
5
6
7
8
9
10
11
12
[oracle@redhat4 admin]$ sqlplus scott/tiger@net_jgl
SQL*Plus: Release 10.2.0.1.0 - Production on Thu Nov 1 21:08:48 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

[oracle@redhat4 admin]$ sqlplus scott/tiger@jgl
SQL*Plus: Release 10.2.0.1.0 - Production on Fri Nov 2 14:05:57 2012
Copyright (c) 1982, 2005, Oracle. All rights reserved.
ERROR:
ORA-12154: TNS:could not resolve the connect identifier specified

所以这里提供了多层的隔离:

1
2
3
4
5
net_service_name ==>> instance_service_name ==>> global_dbname ==>> sid_name ==>> sid
(sid_name=sid=oracle_sid=instance_name)
1> tnsnames.ora中定义了net_service_name和instance_service_name的对应,或者说隔离。
2> lisnter.ora中定义了global_dbname和sid的对应,或者说隔离;
3> 而tnsnames.ora中的instance_service_name(SERVICE_NAME)又和lisnter.ora中的GLOBAL_DBNAME相等。将两层隔离连接起来。

环境设置文件oracle\product\10.1.0\db_1\sqlplus\admin\glogin

参见Oracle的启动和关闭剖析