声明:本文作为学习笔记。
为什么需要数据库事务?
转账是生活中常见的操作,比如从A账户转账100元到B账号。站在用户角度而言,这是一个逻辑上的单一操作,然而在数据库系统中,至少会分成两个步骤来完成:
1.将A账户的金额减少100元
2.将B账户的金额增加100元。
在这个过程中可能会出现以下问题:
1.转账操作的第一步执行成功,A账户上的钱减少了100元,但是第二步执行失败或者未执行便发生系统崩溃,导致B账户并没有相应增加100元。
2.转账操作刚完成就发生系统崩溃,系统重启恢复时丢失了崩溃前的转账记录。
3.同时又另一个用户转账给B账户,由于同时对B账户进行操作,导致B账户金额出现异常。
为了便于解决这些问题,需要引入数据库事务的概念。
数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
一个典型的数据库事务如下所示
BEGIN TRANSACTION //事务开始
SQL1
SQL2
COMMIT/ROLLBACK //事务提交或回滚
对于上面的转账例子,可以将转账相关的所有操作包含在一个事务中
BEGIN TRANSACTION
A账户减少100元
B账户增加100元
COMMIT
1.当数据库操作失败或者系统出现崩溃,系统能够以事务为边界进行恢复,不会出现A账户金额减少而B账户未增加的情况。
2.当有多个用户同时操作数据库时,数据库能够以事务为单位进行并发控制,使多个用户对B账户的转账操作相互隔离。
并非任意的对数据库的操作序列都是数据库事务。数据库事务拥有以下四个特性,习惯上被称之为ACID特性。
数据库事务ACID特性
特性 | 说明 |
---|---|
原子性(Atomicity) | 事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行(失败回滚)。 |
一致性(Consistency) | 事务应确保数据库的状态从一个一致状态转变为另一个一致状态。一致性状态是指:1.系统的状态满足数据的完整性约束(主码,参照完整性,check约束等) 2.系统的状态反应数据库本应描述的现实世界的真实状态,比如转账前后两个账户的金额总和应该保持不变。 |
隔离性(Isolation) | 多个事务并发执行时,一个事务的执行不应影响其他事务的执行。 |
持久性(Durability) | 已被提交的事务对数据库的修改应该永久保存在数据库中。 |
在事务的ACID特性中,C即一致性是事务的根本追求,而对数据一致性的破坏主要来自两个方面
1.事务的并发执行
2.事务故障或系统故障
数据库系统是通过并发控制技术和日志恢复技术来避免这种情况发生的。
先简单介绍下数据库常见的并发异常。
脏读、幻读、不可重复读
异常 | 解释 |
---|---|
脏读 | 脏读是指一个事务读取了另一个事务未提交的数据 |
不可重复读 | 不可重复读是指一个事务对同一数据的读取结果前后不一致。脏读和不可重复读的区别在于:前者读取的是事务未提交的脏数据,后者读取的是事务已经提交的数据,只不过因为数据被其他事务修改过导致前后两次读取的结果不一样 |
幻读 | 幻读是指事务读取某个范围的数据时,因为其他事务的操作导致前后两次读取的结果不一致。幻读和不可重复读的区别在于,不可重复读是针对确定的某一行数据而言,而幻读是针对不确定的多行数据。因而幻读通常出现在带有查询条件的范围查询中 |