为什么要有事务?
- 数据库的出现其实是有应用场景的,最好的例子就是交易,以前的交易是通过账本记录的,也就是通过纸和笔来记录,而数据库的出现大大提升了效率,但是现实中的有些问题,数据库也需要解决的,而事务就是为了解决其中一个问题,下面我们通过一个真实的业务场景来说说为什么要有事务
- A 和 B 是一对朋友,他们都在银行有账户,并且往里面存了 10 元钱,反映到数据库中就是下图:
- 现在A 要给 B 转5元,具体操作如下:
- A 的账户金额少5元
- B 的账户金额多5元
- 这么看还没有什么问题,因为 在现实中看来 就是一个操作 A 给 B 账户转了5元,具体的操作是数据库中的操作,但是问题来了,假设数据库在进行 B 的 账户金额多5元这个操作的时候,突然断电怎么办?我们知道 在对某个页面进行读写访问时,都会先把这个页面加载到Buffer Pool中,之后如果修改了某个页面,也不会立即把修改同步到磁盘,而只是把这个修改了的页面加到Buffer Pool的flush链表中,在之后的某个时间点才会刷新到磁盘。所以这个时候出现意外,导致 A的账户少了5元,但是B的账户并没有多出5元,导致5元不翼而飞,这是一个很严重的问题。
- 怎么解决呢?
- 当然是使用事务,事务如何解决这个问题呢?这个时候就需要理解现实世界中的一些规则
四大规则
原子性
- 现实中做事情要不全做,要不全不做的规则就是原子性
- 比如 刚才转账的行为,不可能只转一半,对于现实来说转账就是一个完整的操作。
隔离性
- 现实中每一步操作都是隔离开的,互不影响的规则就是隔离性
- 比如 A转账B两次,每次都是5 元,那A的账户肯定少10元,B的账户肯定多10元
一致性
- 现实中 数据 始终保持正确,完整和有效
持久性
- 当现实世界的一个状态转换完成后,这个转换的结果将永久的保留,这个规则称为持久性。
事务的概念
- 上面四个特性也是现实世界中状态转换过程需要特性,根据这四个特性我们可以定义一下事务,把需要保证原子性、隔离性、一致性和持久性的一个或多个数据库操作称之为一个事务。
- 事务也有状态的,在不同的阶段,事务主要可以划分为这几个状态:
- 活动:事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态。
- 部分活动:当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在部分提交的状态。
- 失败:当事务处在活动的或者部分提交的状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在失败的状态。
- 中止:如果事务执行了半截而变为失败的状态,就是要撤销失败事务对当前数据库造成的影响。我们把这个撤销的过程称之为回滚
- 提交:当一个处在部分提交的状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了提交的状态。
事务的语法
- 开启事务:
BEGIN ;
START TRANSACTION;
:START TRANSACTION语句后边还可以跟随几个修饰符-
READ ONLY
:标识当前事务是一个只读事务,也就是属于该事务的数据库操作只能读取数据,而不能修改数据。
-
READ WRITE
:标识当前事务是一个读写事务,也就是属于该事务的数据库操作既可以读取数据,也可以修改数据。
-
WITH CONSISTENT SNAPSHOT
:启动一致性读
-
- 提交事务:
COMMIT
- 手动中止事务:
ROLLBACK
:如果语句执行之后发现,执行错误了,这个时候就需要中止事务,回滚到之前的状态
支持事务的引擎
- MySQL中并不是所有存储引擎都支持事务的功能,目前只有InnoDB和NDB存储引擎支持
- 自动提交:在mysql 系统中有一个变量 autocommit ,如果值是 on ,那么我们每次执行一条sql语句就都算是一个独立事务,只有 使用 start transaction 或者 begin 开启一个事务,才不会采用自动提交