数据库事务是构成单一逻辑工作单元的操作集合,通俗讲就是一组SQL语句。
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 事务用来管理 insert,update,delete 语句
Oracle中,事务是隐式开启,MySQL事务是自动提交。就是说:Oracle中,一旦执行了insert之类的语句,数据库默认开启事务,但需要手动提交。而MySQL中,事务都是自动提交的,但需要使用BEGIN 或 START TRANSACTION 显式地开启一个事务。
一、事务的四个特性—ACID
1.1、原子性(Atomicity)
事务包含的的所有操作是一个不可分割的整体,要么全部成功,要么全部失败。不会出现部分成功的情况。
1.2、一致性(Consistency)
事务执行前后,数据库的完整性没有被破坏,事务使数据库从一个一致性状态转换到另一个一致性状态。一致性状态是指:系统的状态满足数据的完整性约束(主码,参照完整性,check约束等) ;系统的状态反应数据库本应描述的现实世界的真实状态,比如转账前后两个账户的金额总和应该保持不变。
1.3、隔离性(Isolation)
并发执行的事务不会相互影响,其对数据库的影响和它们串行执行时一样。比如多个用户同时往一个账户转账,最后账户的结果应该和他们按先后次序转账的结果一样。
1.4、持久性(Durability)
事务一旦提交,对数据库的改变是永久的。
在事务的ACID特性中,C即一致性是事务的根本追求,而对数据一致性的破坏主要来自两个方面
- 事务的并发执行
- 事务故障或系统故障
数据库系统是通过并发控制技术和日志恢复技术来避免这种情况发生的。
并发控制技术保证了事务的隔离性,使数据库的一致性状态不会因为并发执行的操作被破坏。
日志恢复技术保证了事务的原子性,使一致性状态不会因事务或系统故障被破坏。同时使已提交的对数据库的修改不会因系统崩溃而丢失,保证了事务的持久性。
二、事务的并发异常
在多个线程开启数据库事务时,数据库系统必须使其相互隔离,以保证各个线程操作的准确性。
不考虑隔离性时,将产生以下问题:
2.1、脏读
一个事务读取了另一个事务未提交的数据;
2.2、不可重复读
对于某个数据,在一个事务范围内的多次查询间隙,其他事务修改了该数据并提交,导致当前事务前后查询返回了不同结果。
不可重复读与脏读的区别是,脏读读取到了其他事务未提交的数据,而不可重复读是读取到其他事务已提交的数据。
2.3、幻读
指在一个事务内,读取到了别的事务插入的数据,导致前后读取不一致。
幻读与不可重复读的区别是,不可重复读针对确定地某一行数据而言,而幻读是针对不确定的多行数据。因而,幻读通常出现在带有查询条件的范围查询中。
三、事务的隔离级别
SQL标准为事务定义了不同的隔离级别,从低到高依次是:
- 读未提交(READ UNCOMMITTED)
- 读已提交(READ COMMITTED)
- 可重复读(REPEATABLE READ)
- 串行化(SERIALIZABLE)
以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。事务的隔离级别越低,可能出现的并发异常越多,但是通常而言系统能提供的并发能力越强。
在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。