Oracle与MySQL一般性对比

只做大概性的罗列性质的大致化整理,后续部分有代码对比实例,仅做参考,请以更全面具体的专业性文章和手册为准

一、基础架构差异

1. 数据库架构

Oracle

  • 采用”实例-数据库”的多租户架构
  • 一个实例可管理多个PDB(可插拔数据库)
  • 共享内存区域(SGA)设计复杂精细

MySQL

  • 简单直接的”实例-数据库”架构
  • 默认存储引擎InnoDB采用表空间管理
  • 缓冲池(Buffer Pool)是主要内存区域

2. 存储引擎

Oracle

  • 单一存储引擎架构
  • 自动管理所有数据存储细节

MySQL

  • 插件式存储引擎(InnoDB/MyISAM等)
  • 不同引擎特性差异大(如事务支持、锁机制)

二、数据类型差异

1. 数值类型

类型 Oracle MySQL
整数 NUMBER(10) INT/BIGINT
小数 NUMBER(10,2) DECIMAL(10,2)
浮点数 BINARY_FLOAT FLOAT/DOUBLE

2. 字符串类型

类型 Oracle MySQL
定长字符串 CHAR(10) CHAR(10)
变长字符串 VARCHAR2(4000) VARCHAR(65535)
大文本 CLOB LONGTEXT

三、SQL语法差异

1. 分页查询

Oracle

1
2
3
4
SELECT * FROM (
SELECT t.*, ROWNUM rn FROM employees t
WHERE ROWNUM <= 20
) WHERE rn > 10;

MySQL

1
SELECT * FROM employees LIMIT 10, 10;

2. 日期处理

Oracle

1
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM dual;

MySQL

1
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

四、事务与锁机制

1. 事务隔离级别

隔离级别 Oracle支持 MySQL支持
READ UNCOMMITTED
READ COMMITTED ✅(默认)
REPEATABLE READ ✅(默认)
SERIALIZABLE

2. 锁机制

Oracle

  • 行级锁为主
  • 自动升级锁粒度
  • 支持多版本读一致性

**MySQL(InnoDB)**:

  • 行级锁+间隙锁
  • 不自动升级锁粒度
  • MVCC实现机制不同

五、高可用方案

Oracle高可用

  • RAC (Real Application Clusters)
  • Data Guard
  • GoldenGate

MySQL高可用

  • 主从复制
  • Group Replication
  • InnoDB Cluster
  • MHA (Master High Availability)

六、备份恢复机制

Oracle备份

  • RMAN (Recovery Manager)
  • 支持块级别增量备份
  • 时间点恢复精确到秒

MySQL备份

  • mysqldump逻辑备份
  • Percona XtraBackup物理备份
  • 二进制日志(binlog)恢复

七、性能优化差异

Oracle优化

  • 复杂的执行计划管理
  • 丰富的统计信息收集
  • SQL Tuning Advisor

MySQL优化

  • EXPLAIN分析执行计划
  • 慢查询日志分析
  • 索引优化简单直接

八、适用场景建议

选择Oracle当:

  1. 企业级关键业务系统
  2. 需要复杂分析处理
  3. 极高可用性要求
  4. 大数据量高并发场景

选择MySQL当:

  1. Web应用/互联网服务
  2. 快速迭代开发项目
  3. 中小规模数据量
  4. 成本敏感型项目

九、迁移注意事项

  1. 数据类型转换:特别注意NUMBER与DECIMAL的精度处理
  2. SQL重写:分页、序列、日期函数等语法差异
  3. 事务处理:隔离级别和锁行为的差异
  4. 性能调优:执行计划和索引策略需要重新评估

十、未来发展趋势

Oracle

  • 继续强化云服务(Oracle Cloud)
  • 自动化运维方向
  • 多模型数据库支持

MySQL

  • 增强分析处理能力
  • 改进Group Replication
  • 更好的云原生支持

Oracle与MySQL常用语法对照手册

一、分页查询语法对比

1. 标准分页实现

Oracle (12c以下版本):

1
2
3
4
5
6
7
8
9
10
-- 传统ROWNUM三层嵌套写法
SELECT *
FROM (
SELECT t.*, ROWNUM AS rn
FROM (
SELECT * FROM employees ORDER BY hire_date
) t
WHERE ROWNUM <= 20 -- 结束行
)
WHERE rn > 10; -- 起始行

MySQL

1
2
3
4
-- 简洁的LIMIT语法
SELECT * FROM employees
ORDER BY hire_date
LIMIT 10, 10; -- 起始行, 行数

2. 12c+ Oracle新分页语法

1
2
3
4
-- 12c开始支持的FETCH语法
SELECT * FROM employees
ORDER BY hire_date
OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY;

二、序列操作对比

1. 创建序列

Oracle

1
2
3
4
5
6
CREATE SEQUENCE emp_seq
START WITH 100
INCREMENT BY 1
MAXVALUE 999999
NOCYCLE
CACHE 20;

MySQL (AUTO_INCREMENT):

1
2
3
4
5
CREATE TABLE employees (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(100),
PRIMARY KEY (id)
) AUTO_INCREMENT = 100;

2. 获取序列值

Oracle

1
2
3
4
5
-- 获取下一个值
SELECT emp_seq.NEXTVAL FROM dual;

-- 获取当前值
SELECT emp_seq.CURRVAL FROM dual;

MySQL

1
2
3
-- 插入后获取最后ID
INSERT INTO employees (name) VALUES ('张三');
SELECT LAST_INSERT_ID();

三、日期处理对比

1. 当前时间获取

Oracle

1
2
SELECT SYSDATE FROM dual;          -- 系统日期
SELECT CURRENT_TIMESTAMP FROM dual; -- 时间戳

MySQL

1
2
3
SELECT NOW();      -- 当前日期时间
SELECT CURDATE(); -- 当前日期
SELECT CURTIME(); -- 当前时间

2. 日期格式化

Oracle

1
SELECT TO_CHAR(SYSDATE, 'YYYY-MM-DD HH24:MI:SS') FROM dual;

MySQL

1
SELECT DATE_FORMAT(NOW(), '%Y-%m-%d %H:%i:%s');

四、字符串处理对比

1. 字符串连接

Oracle

1
2
3
SELECT first_name || ' ' || last_name AS full_name FROM employees;
-- 或者使用CONCAT函数(只支持两个参数)
SELECT CONCAT(first_name, CONCAT(' ', last_name)) FROM employees;

MySQL

1
2
SELECT CONCAT(first_name, ' ', last_name) AS full_name FROM employees;
-- 或者使用更简洁的||(在ANSI模式下)

2. 子字符串提取

Oracle

1
SELECT SUBSTR('Oracle', 2, 3) FROM dual;  -- 输出'rac'

MySQL

1
2
3
SELECT SUBSTRING('MySQL', 2, 3);  -- 输出'ySQ'
-- 或者简写
SELECT SUBSTR('MySQL', 2, 3);

五、条件表达式对比

1. CASE表达式

Oracle

1
2
3
4
5
6
7
8
SELECT 
employee_name,
CASE
WHEN salary > 10000 THEN '高级'
WHEN salary > 5000 THEN '中级'
ELSE '初级'
END AS level
FROM employees;

MySQL (语法相同):

1
2
3
4
5
6
7
8
SELECT 
employee_name,
CASE
WHEN salary > 10000 THEN '高级'
WHEN salary > 5000 THEN '中级'
ELSE '初级'
END AS level
FROM employees;

2. 特有函数

Oracle特有

1
2
3
4
5
-- NVL空值处理
SELECT NVL(commission_pct, 0) FROM employees;

-- DECODE函数
SELECT DECODE(gender, 'M', '男', 'F', '女', '其他') FROM employees;

MySQL特有

1
2
3
4
5
-- IFNULL空值处理
SELECT IFNULL(commission_pct, 0) FROM employees;

-- IF函数
SELECT IF(salary > 5000, '高薪', '普通') FROM employees;

六、分析函数对比

1. 行号生成

Oracle

1
2
3
4
5
SELECT 
employee_name,
salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;

MySQL (8.0+):

1
2
3
4
5
SELECT 
employee_name,
salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rank
FROM employees;

2. 分组排名

Oracle

1
2
3
4
5
6
SELECT 
department_id,
employee_name,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_rank
FROM employees;

MySQL (8.0+):

1
2
3
4
5
6
SELECT 
department_id,
employee_name,
salary,
RANK() OVER (PARTITION BY department_id ORDER BY salary DESC) AS dept_rank
FROM employees;

七、临时表对比

1. 创建临时表

Oracle

1
2
3
4
5
6
7
8
9
10
11
-- 事务级临时表
CREATE GLOBAL TEMPORARY TABLE temp_emp (
emp_id NUMBER,
emp_name VARCHAR2(100)
) ON COMMIT DELETE ROWS;

-- 会话级临时表
CREATE GLOBAL TEMPORARY TABLE temp_emp_session (
emp_id NUMBER,
emp_name VARCHAR2(100)
) ON COMMIT PRESERVE ROWS;

MySQL

1
2
3
4
5
-- 会话级临时表
CREATE TEMPORARY TABLE temp_emp (
emp_id INT,
emp_name VARCHAR(100)
);

八、事务控制对比

1. 事务语法

Oracle

1
2
3
4
5
6
7
-- 默认每个DML语句就是一个事务(自动提交)
-- 显式事务
SET TRANSACTION READ WRITE;
INSERT INTO accounts VALUES (...);
COMMIT;
-- 或者
ROLLBACK;

MySQL

1
2
3
4
5
6
7
-- 默认自动提交
SET autocommit = 0; -- 关闭自动提交
START TRANSACTION;
INSERT INTO accounts VALUES (...);
COMMIT;
-- 或者
ROLLBACK;

九、存储过程对比

1. 基本结构

Oracle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
CREATE OR REPLACE PROCEDURE raise_salary (
p_emp_id IN NUMBER,
p_amount IN NUMBER
) AS
BEGIN
UPDATE employees
SET salary = salary + p_amount
WHERE employee_id = p_emp_id;

COMMIT;
EXCEPTION
WHEN OTHERS THEN
ROLLBACK;
RAISE;
END;

MySQL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DELIMITER //
CREATE PROCEDURE raise_salary (
IN p_emp_id INT,
IN p_amount DECIMAL(10,2)
)
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
ROLLBACK;
RESIGNAL;
END;

START TRANSACTION;
UPDATE employees
SET salary = salary + p_amount
WHERE employee_id = p_emp_id;

COMMIT;
END //
DELIMITER ;

这篇技术手册详细对比了Oracle和MySQL在关键语法上的差异,特别是重点展示了分页查询的不同实现方式。实际开发中,这些语法差异是数据库迁移或跨数据库开发时需要特别注意的要点。。

Oracle与MySQL面试问答示例

问题1:请说明Oracle和MySQL在分页查询实现上的主要区别?

面试者回答
“在分页查询方面,Oracle和MySQL有显著不同的实现方式:

  1. MySQL使用非常简洁的LIMIT语法:

    1
    SELECT * FROM products ORDER BY price DESC LIMIT 20, 10;

    这表示跳过20条取10条,执行效率很高。

  2. Oracle 11g及以下版本需要使用三层嵌套ROWNUM:

    1
    2
    3
    4
    5
    SELECT * FROM (
    SELECT t.*, ROWNUM rn FROM (
    SELECT * FROM products ORDER BY price DESC
    ) t WHERE ROWNUM <= 30
    ) WHERE rn > 20;

    这种写法比较复杂,但12c版本开始支持了更简单的FETCH语法:

    1
    2
    3
    SELECT * FROM products 
    ORDER BY price DESC
    OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;

实际项目中,MySQL的分页写法更受开发者欢迎,但在处理超大数据量分页时,两种数据库都需要特别注意性能优化。”

问题2:Oracle的NUMBER类型和MySQL的数值类型如何对应?

面试者回答
“在数值类型存储方面,我有这样的理解:

Oracle的NUMBER类型是个”万能”类型,通过指定精度可以表示各种数值:

  • NUMBER(10)对应MySQL的INT
  • NUMBER(10,2)对应MySQL的DECIMAL(10,2)

但需要注意几个关键差异:

  1. Oracle NUMBER默认能存38位精度,而MySQL的DECIMAL最大支持65位
  2. Oracle的NUMBER(5)和NUMBER(5,0)是不同的,前者可能存储小数
  3. 在迁移数据库时,特别要注意NUMBER不带精度的情况,需要评估实际数据范围

在我的上一个项目中,我们就遇到过Oracle的NUMBER(10)迁移到MySQL时,因为实际数据超出INT范围而不得不改用BIGINT的情况。”

问题3:解释下Oracle和MySQL事务隔离级别的实现差异?

面试者回答
“这个问题涉及到两个数据库的核心设计理念:

  1. Oracle默认使用READ COMMITTED隔离级别,通过多版本并发控制(MVCC)实现:
  • 查询只能看到已提交的数据
  • 使用回滚段(Undo Segment)维护数据旧版本
  • 读操作不会阻塞写操作
  1. **MySQL(InnoDB)**默认使用REPEATABLE READ,但通过独特的MVCC实现:
  • 每个事务有自己的一致性视图
  • 通过ReadView和undo log实现
  • 通过间隙锁(Gap Lock)防止幻读

一个重要的实践差异是:在Oracle中,同一个事务内多次查询可能看到不同结果(不可重复读),而MySQL可以保证重复读结果一致。这在我们电商系统的库存控制中非常重要,MySQL的默认隔离级别更适合需要强一致性的场景。”

问题4:如果要从Oracle迁移到MySQL,你会重点关注哪些方面?

面试者回答
“根据我的迁移经验,会重点关注以下方面:

  1. SQL语法改写
  • 分页查询的重写
  • 序列(Sequence)改为AUTO_INCREMENT
  • 日期函数转换(如SYSDATE→NOW())
  1. 数据类型映射
  • VARCHAR2→VARCHAR
  • NUMBER→合适的数值类型
  • CLOB→LONGTEXT
  1. 事务处理
  • 隔离级别差异的影响评估
  • 锁机制差异导致的并发问题
  1. 性能优化
  • 执行计划差异分析
  • 索引策略调整
  • 参数配置优化

在我们最近的人力资源系统迁移项目中,就遇到了Oracle的复杂分析函数在MySQL中性能较差的问题,最终通过业务逻辑拆分和查询重写解决了。我的经验是先做小规模POC验证,再制定详细的迁移检查清单。”

以上内容仅做参考示例,一切以实际项目为准。