🏺 第1章 Oracle 19c 概述
📄 一句话概括

教材讲了三个工具:SQL*Plus(敲命令)、EM(点界面)、DBCA(建库向导)。 它们不是三套数据库,是三个入口,管的是同一个实例。本篇把它们的关系讲清, 再在沙箱里把三条路挨个试一遍。

📝 本章和前面几章的关系

上一篇讲「怎么把库装出来」,这一篇讲「装好之后从哪儿进去」。 这三个工具会在后面每一章反复出现:7、8 章的表空间用 SQLPlus 建, 16 章的备份用 RMAN 命令行,19 章的项目用 Java 客户端连。 先记住一件事:界面会换,SQL 不会。 EM 上点的每一个按钮,背后都是一条 SQL*——所以先学 SQL,界面随时换。

一、SQL*Plus:最老,也最不会消失

SQLPlus 是 Oracle 从第一天就带着的命令行工具。它的地位一直没被取代,原因很实在: 它是唯一一个「任何环境都一定有」的工具——服务器上不一定有图形界面,但一定有它。 它有两种命令,规矩不一样:*

类型 例子 要不要分号
SQL 命令 select * from emp; 要,分号是「执行」的意思
SQL*Plus 命令 desc emp、set linesize 200 不要,回车就执行

这条差别新手最容易卡:敲了 select * from emp 不加分号, 它会显示 2 然后干等——那个 2 是「缓冲区第 2 行」,不是错误。 它在等你把语句写完。 日常用的几条: desc 看表结构、set linesize/pagesize 调显示、spool 把输出存成文件、 @脚本.sql 执行脚本、/ 重跑上一条、! 切到系统命令行。

二、EM 与 DBCA:把命令包成界面

EM(Enterprise Manager) 是浏览器里的管理台。注意它分两种,别搞混: EM Express 是数据库自带的(配一下就能用,功能少); EM Cloud Control 是单独的产品(要另装、另买,能管几百个库)。教材里演示的是前者。 DBCA(Database Configuration Assistant) 是建库向导。 它做的是第 1.3 节装完之后的那一步:装软件不等于有库,软件是程序,库是数据文件加实例。 DBCA 有个容易被忽略的用处:它能「只生成脚本,不执行」。 这个选项价值很高——生产环境建库,标准做法就是先生成脚本、审一遍、再跑, 而不是在界面上点二十下,事后谁也说不清当时选了什么。

三、三个工具,一条线

把三个工具串起来看,它们其实是一条流水线:

阶段 工具 干什么
装软件 安装程序(1.3) 把 Oracle 的程序文件铺到盘上
建库 DBCA 建数据文件、控制文件、日志文件,起实例
日常操作 SQL*Plus / SQL Developer 敲 SQL、建表、查数据
监控与调优 EM / AWR 报表 看性能、找慢 SQL、看等待事件

这条线说明一件事: DBCA 干的是「造库」,SQL*Plus 干的是「用库」,EM 干的是「看库」。 三者不重叠,缺一不可。 所以「学 Oracle 先学哪个」这个问题,答案很明确:SQL。 因为另外两个的产物,最终都要落到 SQL 上。

四、沙箱里的三条路

这一篇的 Demo 会把三条路挨个试一遍:客户端在不在(which sqlplus)、监听端口通不通(1521)、 Python 驱动能不能 import。 三个都失败,但失败的方式不一样,这才是要看的:which 给 None 是「本机没有这个程序」; connect_ex 给非 0 是「端口上没人应答」;import 报 ModuleNotFoundError 是「库没装」。 三种失败对应三层缺失:客户端、服务端、驱动。 排障时先分清是哪一层,否则会一直在装驱动,而问题其实是没有服务端。

五、动手 Demo:三条路挨个测:客户端、端口、驱动

这段代码没有任何 Oracle 依赖,全是标准库——shutil.which 找程序、socket 探端口、 importlib 试导入。这三招在排查任何「连不上」的问题时都用得上。 测完的结论是:三条路一条都不通,所以本课全部改用 SQLite。

import shutil, socket, importlib

# 入口一:客户端在不在
shutil.which('sqlplus')          # None 就是没有

# 入口二:监听端口有没有人应答
s = socket.socket(); s.settimeout(0.5)
s.connect_ex(('127.0.0.1', 1521))   # 0 才是连上了

# 入口三:Python 驱动
for m in ('oracledb', 'cx_Oracle'):
    try:
        importlib.import_module(m); print(m, 'OK')
    except Exception as e:
        print(m, type(e).__name__)

# 三条都不通,于是:能等价的用 SQLite 真跑
c = sqlite3.connect(':memory:'); ...

实跑输出:

--------------------------------------------------------------------
第四课:管理工具——三条路,一条都走不通
--------------------------------------------------------------------

  **教材讲了三个工具:SQL*Plus(敲命令)、企业管理器 EM(点界面)、DBCA(建库向导)。**
  **它们不是三套数据库,是三个入口,管的是同一个实例。**


  入口一:SQL*Plus——本机有没有
  --------------------------------------------------------------------
  `shutil.which('sqlplus')` → **None**
  **None 就是没有。** **没有客户端,连 `sqlplus / as sysdba` 都没得敲。**

  [Oracle 原码 · 本沙箱不执行]
  | sqlplus / as sysdba
  | SQL> SELECT * FROM v$version;


  入口二:监听端口 1521——有没有人在听
  --------------------------------------------------------------------
  `socket.connect_ex(('127.0.0.1', 1521))` → **10035**
  **0 才是「连上了」。**
  **这次拿到的是 10035,在 Windows 上是 `WSAEWOULDBLOCK`:**
  **连接没在超时时间内完成——端口上没人应答。**
  **1521 是 Oracle 监听器的默认端口**,**客户端连远程库时,先连监听、监听再把会话交给实例。**

  入口三:Python 驱动——能不能 import
  --------------------------------------------------------------------
  `import oracledb` → **ModuleNotFoundError**
  `import cx_Oracle` → **ModuleNotFoundError**
  **两个驱动都没有。**
  **就算有,也只是客户端,还得有个真库让它连。**

  三条路都不通,所以本课这么干
  --------------------------------------------------------------------
  **能等价的用 SQLite 真跑;不能等价的贴 Oracle 原码。**
  **判断标准很简单:**
  **这句话换到 SQLite 上语义不变 → 跑;**
  **语义变了或者根本没有对应物 → 只贴原码。**

  SQL> select ename, job, sal from emp where deptno = 10 order by sal desc
  ENAME  JOB       SAL
  ---------------------
  KING   PRESIDENT 5000
  CLARK  MANAGER   2450
  MILLER CLERK     1300
  已选择 3 行
  **上面这条能跑,因为它是标准 SQL,两边语义一样。**
  **下面这条不能跑,因为 `dba_users` 是 Oracle 的数据字典视图:**

  [Oracle 原码 · 本沙箱不执行]
  | SELECT username, account_status FROM dba_users;
    该视图记录全库账号,只有 DBA 能查;SQLite 没有账号体系。


  三个工具分别管什么
  --------------------------------------------------------------------

  SQL> select name, form, job from tool
  NAME     FORM       JOB
  ----------------------------------------------------
  SQL*Plus 命令行     敲 SQL、跑脚本、看执行计划
  EM       浏览器界面 看性能图表、点着做备份、管会话
  DBCA     图形向导   建库、删库、配模板、生成建库脚本
  已选择 3 行
  **三者最终的产物是一样的:**
  **SQL*Plus 敲的 SQL,DBCA 也生成成脚本;EM 上点的按钮,背后也是 SQL。**
  **所以先学 SQL,界面随时换。**

shutil.which 查的是 PATH 环境变量里的可执行文件,不是「装没装」。 装了但没加进 PATH,它照样返回 None。 所以 None 只说明「命令行里敲不出这个命令」,不能直接等同于「没装」。 connect_ex 和 connect 的区别:它不抛异常,直接返回错误码。 0 是成功; Windows 上常见 10061(连接被拒绝,端口有人但服务没起)和 10035(超时,包被丢了或者防火墙挡了)。 这次拿到的是 10035——端口上没人应答。 ModuleNotFoundError 说明的是「Python 找不到这个模块」,和 Oracle 装没装是两件事。 这两个驱动(oracledb、cx_Oracle)都只是客户端,就算装上了,也还得有个真库让它们连。 最后那条 select ... from emp 能跑,是因为它是标准 SQL。 而 dba_users 不能跑,因为它查的是 Oracle 的账号体系—— SQLite 没有账号、没有模式、没有表空间,这一类查询永远演示不了。

30 秒实验

  1. 把 connect_ex 的端口换成 80 和 443,看看本机有没有在跑 Web 服务。 同一段代码,换个端口号就是通用的端口扫描器。
  2. 用 shutil.which 找 python、node、mysql、psql 四个命令,看看这台机器上有几个。 这就是「环境清单」的最简版。
  3. 把 importlib.import_module 换成 sqlite3,确认它一定能成功。 标准库和第三方库的区别,一行代码就能验。

常见误区

  1. 把 sqlplus 装上了就以为有数据库了。 客户端只是「电话机」, 没装服务端就是没人接电话。 这两件事必须分开想。
  2. 在 SQLPlus 里给 SQLPlus 命令加分号。 desc emp; 会报错(SP2-0734), 因为分号会被当成表名的一部分。分号只属于 SQL。
  3. 用 EM 建表,事后说不清建了什么。 界面操作的产物没有留痕, 正规做法是「界面生成脚本 → 审脚本 → 跑脚本」,DBCA 就有这个选项。
自测三问(点开对答案) 1. SQL*Plus 里敲了 `select * from emp` 没加分号,屏幕显示一个 `2`,是什么意思? —— **那个 `2` 是缓冲区行号**,表示第二行已经存进缓冲区, **它在等你继续输入或者打分号。** 不是错误,也没卡死。 2. EM Express 和 EM Cloud Control 差在哪? —— **Express 是数据库自带的**,配一下就能用,只管一个库; **Cloud Control 是单独的产品**,要另装另买,能集中管几百个库。 3. `which sqlplus` 返回 None,能断定这台机器没装 Oracle 吗? —— **不能。** 它只说明 PATH 里没有这个命令。 **可能装了但没配环境变量,也可能是只装了服务端没装客户端工具。**

下一篇讲启动与关闭:startup 三步、shutdown 四档。 这是全书第一次出现「你在哪一步决定你能做什么」的概念, 后面所有运维章节都建立在这个三阶段模型上。

相关笔记