什么是Oracle?

Oracle Database是由Oracle公司开发的关系型数据库管理系统(RDBMS),是目前世界上最流行的企业级数据库之一。它以其强大的功能、高可用性、安全性和可扩展性著称,广泛应用于金融、电信、政府、制造等关键业务领域。

核心特性

1. 企业级特性

  • 高可用性:RAC(Real Application Clusters)、Data Guard
  • 可扩展性:支持大规模并发用户和海量数据
  • 安全性:细粒度访问控制、透明数据加密
  • 性能:高级优化器、并行处理、分区技术

2. 数据完整性

  • 支持ACID事务
  • 参照完整性约束
  • 触发器和存储过程
  • 多版本并发控制(MVCC)

3. 高级功能

  • 分区表和索引
  • 物化视图
  • 高级压缩
  • 内存数据库(TimesTen)

体系结构

1. 物理结构

1
2
3
4
5
6
7
8
9
10
11
12
Oracle实例
├── 内存结构
│ ├── SGA(System Global Area)
│ │ ├── 数据库缓冲区缓存
│ │ ├── 重做日志缓冲区
│ │ └── 共享池
│ └── PGA(Program Global Area)
└── 后台进程
├── DBWn(数据库写入器)
├── LGWR(日志写入器)
├── CKPT(检查点)
└── SMON(系统监视器)

2. 逻辑结构

  • 表空间(Tablespace):数据存储的逻辑单元
  • 段(Segment):表、索引等对象的存储空间
  • 区(Extent):段的存储单元
  • 数据块(Block):最小的I/O单元

基本操作

1. 数据库连接

1
2
3
4
5
6
7
8
-- 使用SQL*Plus连接
sqlplus username/password@database_service

-- 使用SQL Developer连接
-- 配置连接信息:主机、端口、服务名、用户名、密码

-- 使用JDBC连接
-- jdbc:oracle:thin:@//host:port/service_name

2. 用户管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-- 创建用户
CREATE USER test_user IDENTIFIED BY password
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp
QUOTA UNLIMITED ON users;

-- 授权
GRANT CONNECT, RESOURCE TO test_user;
GRANT CREATE SESSION TO test_user;
GRANT CREATE TABLE TO test_user;

-- 修改用户
ALTER USER test_user IDENTIFIED BY new_password;

-- 删除用户
DROP USER test_user CASCADE;

3. 表空间管理

1
2
3
4
5
6
7
8
9
10
11
-- 创建表空间
CREATE TABLESPACE test_ts
DATAFILE '/u01/app/oracle/oradata/ORCL/test_ts01.dbf'
SIZE 100M AUTOEXTEND ON NEXT 10M MAXSIZE 2G;

-- 修改表空间
ALTER TABLESPACE test_ts ADD DATAFILE
'/u01/app/oracle/oradata/ORCL/test_ts02.dbf' SIZE 50M;

-- 删除表空间
DROP TABLESPACE test_ts INCLUDING CONTENTS AND DATAFILES;

表和索引操作

1. 创建表

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
-- 创建基本表
CREATE TABLE employees (
employee_id NUMBER PRIMARY KEY,
first_name VARCHAR2(50) NOT NULL,
last_name VARCHAR2(50) NOT NULL,
email VARCHAR2(100) UNIQUE,
hire_date DATE DEFAULT SYSDATE,
salary NUMBER(10,2) CHECK (salary > 0),
department_id NUMBER,
CONSTRAINT fk_department
FOREIGN KEY (department_id)
REFERENCES departments(department_id)
);

-- 创建带分区的表
CREATE TABLE sales (
sale_id NUMBER,
sale_date DATE,
amount NUMBER(10,2),
region VARCHAR2(50)
)
PARTITION BY RANGE (sale_date) (
PARTITION sales_q1 VALUES LESS THAN (TO_DATE('2024-04-01', 'YYYY-MM-DD')),
PARTITION sales_q2 VALUES LESS THAN (TO_DATE('2024-07-01', 'YYYY-MM-DD')),
PARTITION sales_q3 VALUES LESS THAN (TO_DATE('2024-10-01', 'YYYY-MM-DD')),
PARTITION sales_q4 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD'))
);

2. 索引操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 创建B树索引
CREATE INDEX idx_employees_last_name ON employees(last_name);

-- 创建唯一索引
CREATE UNIQUE INDEX idx_employees_email ON employees(email);

-- 创建位图索引(适用于低基数列)
CREATE BITMAP INDEX idx_employees_dept ON employees(department_id);

-- 创建函数索引
CREATE INDEX idx_employees_upper_name ON employees(UPPER(first_name));

-- 创建分区索引
CREATE INDEX idx_sales_date ON sales(sale_date) LOCAL;

PL/SQL编程

1. 基本语法

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
-- 创建存储过程
CREATE OR REPLACE PROCEDURE update_salary(
p_emp_id IN NUMBER,
p_increase_pct IN NUMBER
) AS
v_current_salary NUMBER;
BEGIN
SELECT salary INTO v_current_salary
FROM employees
WHERE employee_id = p_emp_id;

UPDATE employees
SET salary = salary * (1 + p_increase_pct/100)
WHERE employee_id = p_emp_id;

COMMIT;

DBMS_OUTPUT.PUT_LINE('Salary updated successfully');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Employee not found');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM);
ROLLBACK;
END;
/

-- 调用存储过程
EXEC update_salary(1001, 10);

2. 函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 创建函数
CREATE OR REPLACE FUNCTION get_employee_name(
p_emp_id IN NUMBER
) RETURN VARCHAR2 IS
v_full_name VARCHAR2(100);
BEGIN
SELECT first_name || ' ' || last_name
INTO v_full_name
FROM employees
WHERE employee_id = p_emp_id;

RETURN v_full_name;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RETURN 'Employee not found';
END;
/

-- 使用函数
SELECT get_employee_name(1001) FROM dual;

3. 触发器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
-- 创建触发器
CREATE OR REPLACE TRIGGER trg_employees_audit
AFTER INSERT OR UPDATE OR DELETE ON employees
FOR EACH ROW
DECLARE
v_action VARCHAR2(10);
BEGIN
IF INSERTING THEN
v_action := 'INSERT';
ELSIF UPDATING THEN
v_action := 'UPDATE';
ELSIF DELETING THEN
v_action := 'DELETE';
END IF;

INSERT INTO employees_audit (
employee_id, action, action_date, old_salary, new_salary
) VALUES (
:OLD.employee_id, v_action, SYSDATE, :OLD.salary, :NEW.salary
);
END;
/

高级查询

1. 分析函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
-- 排名函数
SELECT employee_id, first_name, salary,
RANK() OVER (ORDER BY salary DESC) as salary_rank,
DENSE_RANK() OVER (ORDER BY salary DESC) as dense_rank,
ROW_NUMBER() OVER (ORDER BY salary DESC) as row_num
FROM employees;

-- 分区分析
SELECT department_id, employee_id, first_name, salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) as dept_rank,
SUM(salary) OVER (PARTITION BY department_id) as dept_total_salary
FROM employees;

-- 移动平均
SELECT employee_id, hire_date, salary,
AVG(salary) OVER (ORDER BY hire_date ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING) as moving_avg
FROM employees;

2. 子查询和集合操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
-- 相关子查询
SELECT e.employee_id, e.first_name, e.salary
FROM employees e
WHERE e.salary > (
SELECT AVG(salary)
FROM employees
WHERE department_id = e.department_id
);

-- 集合操作
SELECT employee_id FROM employees
UNION
SELECT manager_id FROM departments;

SELECT employee_id FROM employees
INTERSECT
SELECT manager_id FROM departments;

SELECT employee_id FROM employees
MINUS
SELECT manager_id FROM departments;

性能优化

1. 执行计划分析

1
2
3
4
5
6
7
8
9
10
11
12
-- 查看执行计划
EXPLAIN PLAN FOR
SELECT * FROM employees e, departments d
WHERE e.department_id = d.department_id
AND e.salary > 5000;

-- 显示执行计划
SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY);

-- 使用AUTOTRACE
SET AUTOTRACE ON;
SELECT * FROM employees WHERE department_id = 10;

2. 索引优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-- 创建复合索引
CREATE INDEX idx_emp_dept_salary ON employees(department_id, salary);

-- 索引提示
SELECT /*+ INDEX(employees idx_emp_dept_salary) */ *
FROM employees
WHERE department_id = 10;

-- 收集统计信息
BEGIN
DBMS_STATS.GATHER_TABLE_STATS('HR', 'EMPLOYEES');
DBMS_STATS.GATHER_INDEX_STATS('HR', 'IDX_EMP_DEPT_SALARY');
END;
/

3. 分区优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-- 创建分区表
CREATE TABLE sales_range (
sale_id NUMBER,
sale_date DATE,
amount NUMBER(10,2)
)
PARTITION BY RANGE (sale_date) (
PARTITION p2023 VALUES LESS THAN (TO_DATE('2024-01-01', 'YYYY-MM-DD')),
PARTITION p2024 VALUES LESS THAN (TO_DATE('2025-01-01', 'YYYY-MM-DD')),
PARTITION pmax VALUES LESS THAN (MAXVALUE)
);

-- 分区查询优化
SELECT * FROM sales_range PARTITION (p2024)
WHERE sale_date BETWEEN '2024-01-01' AND '2024-12-31';

高可用性

1. Data Guard

1
2
3
4
5
6
7
-- 主库配置
ALTER SYSTEM SET LOG_ARCHIVE_DEST_1='LOCATION=/u01/app/oracle/oradata/ORCL/arch';
ALTER SYSTEM SET LOG_ARCHIVE_DEST_2='SERVICE=standby_db LGWR ASYNC';
ALTER SYSTEM SET LOG_ARCHIVE_DEST_STATE_2=ENABLE;

-- 创建备用库
RMAN> DUPLICATE TARGET DATABASE FOR STANDBY FROM ACTIVE DATABASE;

2. RAC配置

1
2
3
4
5
# 安装Grid Infrastructure
# 配置共享存储
# 创建集群数据库
srvctl add database -d orcl -o /u01/app/oracle/product/19c/dbhome_1
srvctl start database -d orcl

安全管理

1. 权限管理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-- 创建角色
CREATE ROLE hr_manager;
GRANT SELECT, INSERT, UPDATE, DELETE ON employees TO hr_manager;
GRANT SELECT ON departments TO hr_manager;

-- 授予角色给用户
GRANT hr_manager TO john_doe;

-- 细粒度访问控制
BEGIN
DBMS_RLS.ADD_POLICY(
object_schema => 'HR',
object_name => 'EMPLOYEES',
policy_name => 'EMP_DEPT_POLICY',
function_schema => 'HR',
policy_function => 'EMP_DEPT_FUNCTION',
statement_types => 'SELECT, UPDATE, DELETE'
);
END;
/

2. 数据加密

1
2
3
4
5
6
7
8
9
-- 透明数据加密
ALTER TABLE employees MODIFY (salary ENCRYPT USING 'AES256');

-- 创建加密列
CREATE TABLE sensitive_data (
id NUMBER PRIMARY KEY,
credit_card VARCHAR2(20) ENCRYPT,
ssn VARCHAR2(11) ENCRYPT
);

备份与恢复

1. RMAN备份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 连接到RMAN
rman target /

# 全库备份
RMAN> BACKUP DATABASE PLUS ARCHIVELOG;

# 增量备份
RMAN> BACKUP INCREMENTAL LEVEL 1 DATABASE;

# 表空间备份
RMAN> BACKUP TABLESPACE users;

# 恢复数据库
RMAN> RESTORE DATABASE;
RMAN> RECOVER DATABASE;

2. 逻辑备份

1
2
3
4
5
# 使用Data Pump导出
expdp hr/hr@orcl schemas=hr directory=DATA_PUMP_DIR dumpfile=hr_backup.dmp logfile=hr_export.log

# 使用Data Pump导入
impdp hr/hr@orcl schemas=hr directory=DATA_PUMP_DIR dumpfile=hr_backup.dmp logfile=hr_import.log

与Java集成

1. JDBC连接

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
import java.sql.*;

public class OracleConnection {
public static void main(String[] args) {
String url = "jdbc:oracle:thin:@//localhost:1521/orcl";
String user = "hr";
String password = "hr";

try (Connection conn = DriverManager.getConnection(url, user, password)) {
String sql = "SELECT employee_id, first_name, salary FROM employees WHERE ROWNUM <= 10";

try (PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {

while (rs.next()) {
System.out.println("ID: " + rs.getInt("employee_id") +
", Name: " + rs.getString("first_name") +
", Salary: " + rs.getBigDecimal("salary"));
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}

2. 连接池配置

1
2
3
4
5
6
7
8
9
10
11
<!-- context.xml -->
<Resource name="jdbc/oracle"
auth="Container"
type="javax.sql.DataSource"
driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@//localhost:1521/orcl"
username="hr"
password="hr"
maxActive="20"
maxIdle="10"
maxWait="-1"/>

常见应用场景

  1. 金融行业:银行核心系统、证券交易系统
  2. 电信行业:计费系统、客户关系管理
  3. 政府系统:人口管理、税务系统
  4. 制造业:ERP系统、供应链管理
  5. 医疗行业:电子病历、医院信息系统

优缺点分析

优点

  • 功能最完整的企业级数据库
  • 极高的可靠性和稳定性
  • 强大的PL/SQL编程能力
  • 完善的高可用解决方案
  • 优秀的性能优化工具

缺点

  • 商业授权费用昂贵
  • 系统资源消耗大
  • 管理复杂度高
  • 学习曲线陡峭

学习资源推荐

  • 官方文档https://docs.oracle.com/en/database/
  • 认证考试:Oracle OCP认证
  • 书籍:《Oracle Database 19c完全参考手册》、《Oracle性能优化艺术》
  • 实践项目:企业级ERP系统、金融交易平台

总结

Oracle作为企业级数据库的霸主,凭借其无与伦比的功能完整性、可靠性和性能,成为大型企业和关键业务系统的首选。虽然成本较高,但对于需要处理海量数据、高并发访问和复杂业务逻辑的企业级应用,Oracle仍然是最佳选择。掌握Oracle对于数据库管理员和企业级开发者来说是必备技能。