mysql运行原理笔记-事务

Scroll Down

事务简介

事务的起源

对于大部分程序来说,他们的任务就是把现实世界的业务场景映射到数据库世界中。

原子性(Atomicity)

在现实世界中,转账操作是一个不可分割的操作。如果在执行操作的过程中发生了错误,就把已经执行的操作恢复成没有执行之前的样子。

隔离性(Isolation)

对于现实世界中状态转换对应的某些数据库操作来说,不仅要保证这些操作以原子性的方式执行完成,而且要保证其他的状态转换不会影响到本次状态转换,这个规则称为隔离性。

一致性(Consistency)

持久性(Durability)

当现实世界中的一个状态转换完成后,这个转换的结果将永久保留,这个规则称为持久性。

事务的概念

需要保证原子性、隔离性、一致性和永久性的一个或多个数据库操作称为事务。
事务是一个抽象的概念,它其实对应着一个或多个数据库操作。事务大致划分成下面几个状态。

  • 活动的(active):事务对应的数据库操作正在执行过程中时,我们就说该事务处于活动状态。
  • 部分提交的(partially committed):当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的的影响并没有刷新到磁盘时,我们就说该事务处于部分提交的状态。
  • 失败的(failed):当事务处于活动的状态或者部分提交状态时,可能遇到某些错误而无法继续执行,或者人为停止了当前事务的执行,我们就说该事务处于失败的状态
  • 中止的(aborted):如果事务执行了半截而变为失败的状态,此时需要回滚操作,当回滚操作执行完毕后,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处于中止的状态。
  • 提交的(committed):当一个处于部分提交的状态事务将修改过的数据都刷新到磁盘中之后,我们就可以说该事务处于提交的状态。
    只有当事务处于提交的或者中止的状态时,一个事务的生命周期才算结束了。该事务对数据库所做的修改将永久生效;对于处于中止状态的事务来说,该事务对数据库所做的所有修改都会被回滚到没有执行该事务之前的状态。

MySQL中事务的语法

开启事务

可以使用下面两种语句来开启一个事务。

  • BEGIN[WORK];BEGIN语句代表开启了一个事务,后边的单词WORK可有可无。开启事务后,就可以继续写若干条语句,这些语句都属于刚刚开启的这个事务。
  • START TRANSACTION;START TRANSACTION语句与BEGIN语句有相同的功能,都标志着开启一个事务。
    如果不显式指定事务的访问模式,那么该事务的访问模式就是读写模式。

提交事务

开启事务之后就可以继续编写需要放到该事务中的语句了。当最后一条语句写完后就可以提交该事务了。提交的语句也很简单;

COMMIT [WORK];

COMMIT语句就代表提交一个事务,后边的WORK可有可无。

手动中止事务

如果我们写了几条语句之后发现前面某些语句写错了,可以手动使用下面这个语句将数据库恢复到事务执行之前的样子。

ROLLBACK [WORK];

ROLLBACK语句代表回滚一个事务,后边的WORK可有可无。

支持事务的存储引擎

在MySQL中,并不是所有的存储引擎都支持事务的功能,目前只有InnoDB和NDB存储的引擎支持。如果某个事务中包含的语句要修改某个表中的数据,但是该表使用的存储引擎不支持事务,那么对该表所做的修改无法进行回滚。

自动提交

MySQL中有一个系统变量autocommit,用来自动提交事务。它的默认值是ON。如果不显式地使用START TRANSACTION或者BEGIN语句开启一个事务,那么每一条语句都算是一个独立的事务,这种特性称为事务的自动提交。
当然,如果想关闭这种自动提交的功能,可以使用下面两种方法。

  • 显式地使用START TRANSACTION或者BEGIN语句开启一个事务。这样在本次事务提交或者回滚前会暂时关闭自动提交的功能。
  • 把系统变量autocommit的值设置为OFF。

隐式提交

当使用START TRANSACTION或者BEGIN语句开启了一个事务,或者把系统变量autocommit的值设置为OFF时,事务就不会进行自动提交。如果我们输入了某些语句,且这些语句会导致之前的事务悄悄地提交掉,那么这种因为某些特殊的语句而导致事务提交的情况称为隐式提交。会导致事务隐式提交的语句有下面这些。

  • 定义或修改数据库对象的数据定义语言(DDL)。
  • 隐式使用或修改MySQL数据库中的表。
  • 事务控制或关于锁定的语句。当我们在一个事务还没提交或者还没回滚时就又使用了START TRANSACTION或者BEGIN语句开启了另一个事务,此时会隐式地提交上一个事务。
  • 加载数据的语句。
  • 关于MySQL复制的一些语句

保存点

如果你已经开启了一个事务,并且已经输入了很多语句,这时忽然发现前面已经执行完成的某个语句的参数写错了,只好使用ROLLBACK语句来让数据库状态恢复到事务执行之前的样子,然后一切从头再来。
设计者提出了保存点(savepoint)的概念,就是在事务对应的数据库语句中打好几个点。我们在调用ROLLBACK语句时可以指定回滚到哪个点,而不是回到最初的原点,定义保存点的语法如下:

SAVEPOINT 保存点名称;

当想回滚到某个保存点时,可以使用下面这个语句:

ROLLBACK [WORK] TO [SAVEPOINT] 保存点名称;

如果ROLLBACK语句后面不跟随保存点名称,则直接回滚到事务执行之前的状态。
如果想要删除某个保存点,可以使用这个语句:

RELEASE SAVEPOINT 保存点名称;