在数据库管理领域,事务是确保数据一致性和完整性的核心机制,它允许用户将一系列操作视为一个不可分割的整体,要么全部成功执行,要么全部回滚。MySQL 和 Oracle 作为两款广泛使用的关系型数据库管理系统,它们在事务处理方面既有共性,也存在诸多差异。接下来,我们将深入探讨 MySQL 和 Oracle 事务的详细内容,并对比两者的区别。
MySQL事务详解
事务的概念和特性
事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
注:默认MySQL的事务是自动提交的,也就是说,当执行一条DML语句,MySQL会立即隐式的提交事务。
Oracle需要显示提交事务,plsql软件可通过设置自动提交
存储引擎
存储引擎就是存储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可称为表类型。
innoDB引擎
innoDB引擎是一种兼顾可靠性和高性能的通用存储引擎。
特点:DML操作遵循ACID模型,支持事务行级锁,提高并发访问功能,支持外键foreign key约束,保证数据的完整性和正确性。
事务四大特性
- 原子性(Atomicity):事务中的操作是一个不可分割的最小单元,要么全部执行,要么全部不执行。例如,在银行转账操作中,从账户 A 扣除金额和向账户 B 增加金额这两个操作必须同时成功或失败,不能出现 A 账户扣钱但 B 账户未到账的情况。
- 一致性(Consistency):事务执行前后,数据库始终处于合法的状态。假设数据库中定义了某张表的字段必须满足特定约束,如主键唯一、外键关联正确等,事务执行后,这些约束依然要得到保证。
- 隔离性(Isolation):多个事务并发执行时,一个事务的执行不能被其他事务干扰,每个事务都感觉像是在独立使用数据库。
- 持久性(Durability):一旦事务提交,其对数据库所做的修改就会永久保存,即使系统发生故障(如停电、宕机等)也不会丢失。
事务并发时存在的问题
脏读(Dirty Read)
脏数据所指的就是未提交的数据,而脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
例:一个事务正对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态(可能提交也可能回滚),此时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。
不可重复读(Non-repeatable Read)
一个事务先后读取同一条记录,而事务在两次读取之间该数据被其他事务所修改,则两次读取的数据不同,我们称为不可重复读。
例:事务1在读取某一数据,而事务2立马修改了这个数据并提交事务给数据库,事务1再次读取该数据就得到了不同的结果,发生了不可重复读。
不可重复读和脏读的区别:脏读是某一个事务读取了另一个事务未提交的事务,而不可重复读则是在同一事务内读取了前一事务提交的数据,即前一次读到的数据是另一个事务提交前,后一次读到的数据是提交后的。
幻读(Phantom Read)
一个事物按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足查询跳到的新数据,这种现象称为幻读,幻读是指当事务不是独立执行时发生的一种现象。
幻读和不可重复读的区别:幻读和不可重复读都是读取了另一条已经提交的事务(这点和脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体。
四个隔离级别
MySQL 支持四种事务隔离级别,不同的隔离级别会影响事务之间的并发行为和数据一致性:
- 读未提交(Read Uncommitted):这是最低的隔离级别,虽然拥有超高的并发处理能力和很低的系统开销,但很少用于实际应用。一个事务可以读取另一个未提交事务的数据。这种隔离级别可能会出现脏读、不可重复读和幻读问题 。
- 读已提交(Read Committed):一个事务只能读取已提交事务的数据。它避免了脏读,但仍可能出现不可重复读和幻读问题。Oracle 数据库默认的隔离级别就是读已提交。
- 可重复读(Repeatable Read):在一个事务内,多次读取同一数据时,结果始终保持一致,即使其他事务对该数据进行了修改并提交。MySQL 默认的隔离级别是可重复读,它通过多版本并发控制(MVCC)机制避免了脏读和不可重复读,但在某些情况下,幻读问题依然可能存在 。
- 可串行化(Serializable):这是最高的隔离级别,它通过强制事务串行执行,避免了所有的并发问题,包括脏读、不可重复读和幻读。但由于事务只能一个接一个地执行,会极大地降低数据库的并发性能。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
可串行化 | × | × |
Oracle 事务详解
事务的概念与特性
Oracle 中的事务同样遵循 ACID 特性,其核心概念与 MySQL 类似,将一组操作作为一个整体,保证数据的一致性和完整性。例如,在企业的订单处理系统中,创建订单、扣除库存、更新客户余额等操作会被封装在一个事务内,确保整个业务流程的正确执行。
注:Oracle的事务特性和事务并发时存在的问题与MySQL相同。
存储引擎
Oracle 的 “单一存储引擎” 设计确保了数据在事务处理、数据分析、高可用性等场景下的一致性和兼容性。用户可通过调整存储参数(如块大小、压缩方式、分区策略)和选择合适的数据组织方式(如表类型、索引结构),灵活应对不同的业务需求。这与 MySQL 等支持多存储引擎(如 InnoDB、MyISAM)的数据库形成鲜明对比,体现了 Oracle 在企业级数据管理中的一体化设计理念。
事务的隔离级别
Oracle支持两种主要的事务隔离级别:
- 读已提交(Read Committed):这是 Oracle 的默认隔离级别,它保证事务只能读取其他事务已经提交的数据,避免了脏读。在该隔离级别下,对于相同的查询,每次执行可能会得到不同的结果(因为其他事务可能提交了新的数据修改),存在不可重复读和幻读问题。
- 可串行化(Serializable):与 MySQL 的可串行化隔离级别类似,它通过对数据加锁,使事务按照顺序依次执行,从而避免了所有的并发问题。但这种方式会严重影响数据库的并发性能,因此在实际应用中,除非对数据一致性要求极高且并发量较低的场景,一般较少使用 。此外,Oracle 还提供了一种基于多版本的读一致性机制(Read Consistency),它允许事务在查询数据时获取到一个一致性的快照,即使在查询过程中有其他事务修改了数据,也不会影响当前事务的查询结果,在一定程度上缓解了并发读取时的数据不一致问题 。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读已提交(默认) | 否 | 是 | 是 |
可串行化 | 否 | 否 | 否 |
事务操作
查看MySQL支持哪些引擎。
show engines; -- 当前MySQL版本支持哪些引擎
注:innoDB支持事务,myisam、memory等不支持事务
查看MySQL当前默认的存储引擎。
show variables like '%storage_engine%';
注:MySQL 5.5版本前,默认存储引擎是MyISAM
MySQL 5.5版本后,默认存储引擎是innoDB
显示自动提交事务的状态(insert、update、delete)
show variables like 'autoconmit';
开启事务
-- MySQL
set @@autocommit=0 ; -- 将自动提交事务关闭,只对当前对话有效
set @@autocommit=1 ; -- 设置自动提交事务begin; -- 开启事务
start transaction; -- 开启事务-- Oracle
-- 执行DML语句,隐式开启事务
UPDATE employees SET salary = salary * 1.1 WHERE department_id = 10;
提交事务
-- MySQL
select @@autoconmit; -- 查询结果为1自动提交
set @@autocommit=0 ; -- 为0手动提交commit; -- 提交事务(成功)
rollback; -- 回滚事务(失败)-- Oracle
-- 查询自动提交事务
SHOW AUTOCOMMIT;
-- 输出:AUTOCOMMIT OFF(关闭自动提交) 或 AUTOCOMMIT ON(开启自动提交)-- 设置自动提交格式
SET AUTOCOMMIT ON; -- 开启自动提交(每条SQL执行后自动COMMIT)
SET AUTOCOMMIT OFF; -- 关闭自动提交(默认行为)
-- 事务的提交与回滚
UPDATE employees SET salary = salary*1.1 WHERE department_id = 10;
-- 执行多个DML语句...COMMIT; -- 提交所有更改
ROLLBACK; -- 回滚所有更改
MySQL和Oracle事务区别总结
隔离级别支持
MySQL 支持四种完整的事务隔离级别,而 Oracle 主要支持读已提交和可串行化两种隔离级别。虽然 Oracle 也有读一致性机制,但与 MySQL 的隔离级别概念有所不同。MySQL 的可重复读隔离级别通过 MVCC 在一定程度上解决了幻读问题,而 Oracle 的读已提交隔离级别下幻读问题依然较为突出,需要通过其他机制(如显式加锁)来处理 。
事务控制语句
虽然两者都有开启事务、提交事务和回滚事务的语句,但在具体使用和功能上存在细微差别。例如,MySQL 的 START TRANSACTION 和 BEGIN 功能基本相同,都用于显式开启事务;而 Oracle 的 BEGIN 通常用于开启一个匿名块,隐式开启事务 。在保存点的使用上,Oracle 提供了更丰富的语句来管理保存点,如 ROLLBACK TO SAVEPOINT AND RELEASE SAVEPOINT ,相比之下,MySQL 在保存点管理方面的功能相对简单 。
性能表现
在事务处理性能方面,由于 MySQL 的隔离级别和锁机制更加灵活,在一些高并发且对数据一致性要求不是极高的场景下,MySQL 可能具有更好的并发性能。而 Oracle 的事务处理机制更侧重于数据的一致性和完整性,在复杂的企业级应用中,尤其是对数据准确性要求严格的场景下,Oracle 能够提供更可靠的事务保障,但在高并发场景下,其性能可能会受到一定影响 。
综上所述,MySQL 和 Oracle 在事务处理方面各有特点。在实际应用中,需要根据具体的业务需求、数据一致性要求和并发量等因素,选择合适的数据库及事务处理策略。
求点赞、求关注、求收藏!!!会继续发布关于数据开发方面的博客!