文章目录
- 前言:本博文是对MySQL是怎样运行的:从根儿上理解MySQL这本书的归纳和总结
- 19.从猫爷被杀说起-事务简介
- 1.事务的起源
- 1.1 原子性(Atomicity)
- 1.2 隔离性(Isolation)
- 1.3 一致性(Consistency)
- 1.4 持久性(Durability)
- 2.事务(transaction)的概念
- 3.MySQL中事务的语法
- 3.1 开启事务
- 3.1.1 START TRANSACTION
- 3.2 提交事务
- 3.3 手动中止事务
- 3.4 支持事务的存储引擎
- 3.5 自动提交
- 3.6 隐式提交
- 3.7 保存点
前言:本博文是对MySQL是怎样运行的:从根儿上理解MySQL这本书的归纳和总结
19.从猫爷被杀说起-事务简介
1.事务的起源
这里书中讲述的十分生动有趣,大家可自行下载pdf查阅理解;总结来说所谓事务就是:让某些数据库操作符合现实世界中状态转换的规则
1.1 原子性(Atomicity)
- 概述
现实世界中转账操作是一个不可分割的操作,也就是说要么压根儿就没转,要么转账成功,不能存在中间的状态,也就是转了一半的这种情况。设计数据库的大叔们把这种要么全做,要么全不做的规则称之为 原子性,但麻烦就麻烦在现实生活中一步的操作要在数据库分为好几步来实现,其中一环断开则会引发意想不到的效果,所以保证原子性是非常重要的
1.2 隔离性(Isolation)
- 概述
当在现实世界中转账100可以分为两次进行,但在数据库中两次分别代表着两次的状态转换,这两次的状态转换不能相互影响,细分就是其中的步骤不能影响其他的状态转换。所以不仅要保证这些操作以 原子性 的方式执行完成,而且要保证其它的状态转换不会影响到本次状态转换,这个规则被称之为 隔离性 。
- 图示
1.3 一致性(Consistency)
- 概述
只有符合这些约束的数据才是有效的,数据库世界只是现实世界的一个映射,现实世界中存在的约束当然也要在数据库世界中有所体现。如果数据库中的数据全部符合现实世界中的约束
(all defined rules)
,我们说这些数据就是一致的,或者说符合 一致性 的。
- 两方面保证一致性
- 数据库自身保证一部分,例如什么主键外键,不符合规范就会报错,还有check语法来支持自定义约束,不过在mysql没用,只是支持并不会检查你的数据是否符合check。但什么sql server和oracle会切实的检查
- 更多的一致性需求需要靠写业务代码的程序员自己保证,需要考虑问题规模
- 总结
原子性 和 隔离性 都会对 一致性 产生影响,比如我们现实世界中转账操作完成后,有一个 一
致性 需求就是参与转账的账户的总的余额是不变的。如果数据库不遵循 原子性 要求,也就是转了一半就不转了,那最后就是不符合一致性需求的;类似的,如果数据库不遵循 隔离性 要求,例如上面所说,也就是说不符合 一致性 需求了。所以说,数据库某些操作的原子性和隔离性都是保证一致性的一种手段,在操作执行完成后保证符合所有既定的约束则是一种结果。注意:保证了其原子性和隔离性也不一定能保证一致性,只要最后的结果符合所有现实世界中的约束,那么就是符合 一致性 的。
1.4 持久性(Durability)
- 概述
当现实世界的一个状态转换完成后,这个转换的结果将永久的保留,这个规则被设计数据库的大叔们称为 持久性 。当把现实世界的状态转换映射到数据库世界时, 持久性 意味着该转换对应的数据库操作所修改的数据都应该在磁盘上保留下来,不论之后发生了什么事故,本次转换造成的影响都不应该被丢失掉
2.事务(transaction)的概念
- 概述
ACID:原子性( Atomicity )、 隔离性 ( Isolation )、 一致性 ( Consistency )和 持久性 ( Durability )
- 事务的不同状态
- 活动的:事务对应的数据库操作正在执行过程中时,我们就说该事务处在 活动的 状态
- 部分提交的:当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我们就说该事务处在 部分提交的 状态。例如脏页的刷新
- 失败的:当事务处在 活动的 或者 部分提交的 状态时,可能遇到了某些错误(数据库自身的错误、操作系统错误或者直接断电等)而无法继续执行,或者人为的停止当前事务的执行,我们就说该事务处在 失败的 状态。
- 中止的:如果事务执行了半截而变为 失败的 状态,换句话说,就是要撤销失败事务对当前数据库造成的影响。书面一点的话,我们把这个撤销的过程称之为 回滚 。当 回滚 操作执行完毕时,也就是数据库恢复到了执行事务之前的状态,我们就说该事务处在了 中止的 状态。
- 提交的:当一个处在 部分提交的 状态的事务将修改过的数据都同步到磁盘上之后,我们就可以说该事务处在了 提交的 状态
- 状态转换图
从图中大家也可以看出了,只有当事务处于提交的或者中止的状态时,一个事务的生命周期才算是结束了。对于已经提交的事务来说,该事务对数据库所做的修改将永久生效,对于处于中止状态的事务,该事务对数据库所做的所有修改都会被回滚到没执行该事务之前的状态。
3.MySQL中事务的语法
3.1 开启事务
mysql为我们提供了两种开启事务的方式:这两种方式起到的效果是一样一样的,不过TRANSACTION比BEGIN稍微厉害一点
BEGIN;------>加入事务的语句.......;
START TRANSACTION
3.1.1 START TRANSACTION
厉害就厉害在这个语句后面可以跟几个修饰符,你可以试试只读和读写能同时设置吗?
-
READ ONLY
:标识当前事务是一个只读事务,也就是属于该事务的数据库操作只能读取数据,而不能修改数据。
小贴士:其实只读事务中只是不允许修改那些其他事务也能访问到的表中的数据(类似锁与共享数据希望你心里有数),对于临时表来说(我们使用CREATE TMEPORARY TABLE创建的表),由于它们只能在当前会话中可见,所以只读事务其实也是可以对临时表进行增、删、改操作的。
-
READ WRITE
:标识当前事务是一个读写事务,也就是属于该事务的数据库操作既可以读取数据,也可以修改数据。 -
WITH CONSISTENT SNAPSHOT
:启动一致性读
3.2 提交事务
- 概述
开启事务之后就可以继续写需要放到该事务中的语句了,当最后一条语句写完了之后,我们就可以提交该事务了,提交的语句也很简单:
COMMIT [WORK]
,COMMIT
语句就代表提交一个事务,后边的WORK
可有可无。
3.3 手动中止事务
- 概述
如果我们写了几条语句之后发现上边的某条语句写错了,我们可以手动的使用下边这个语句来将数据库恢复到事务执行之前的样子:
ROLLBACK [WORK]
,ROLLBACK
语句就代表中止并回滚一个事务,后边的WORK
可有可无类似的。
- 注意
这里需要强调一下, ROLLBACK 语句是我们程序员手动的去回滚事务时才去使用的,如果事务在执行过程中遇到了某些错误而无法继续执行的话,事务自身会自动的回滚。
- 小贴士
这些命令行指令是越用越少,读者们可以多多了解下对这些操作的更高一级的封装,类似JDBC
3.4 支持事务的存储引擎
- 概述
并不是所有存储引擎都是支持事务的,现在只有InooDB、NDB
支持事务,类似于MyISAM、Memory
都是不支持的,所以当我们使用这些不支持事务的引擎时我们对表的修改是无法进行回滚的,这里读者可以试试创建两个不同的表使用不同的引擎来增删改数据并进行回滚看看效果
3.5 自动提交
- 概述
从下图可以看到默认是开启状态,也就是说我们不用手动开启事务每一个语句都算是独立事务,即为自动提交,你如果想关掉就手动开启事务或者把这个系统变量设置为OFF
,这样的话,我们写入的多条语句就算是属于同一个事务了,直到我们显式的写出 COMMIT 语句来把这个事务提交掉,或者显式的写出 ROLLBACK 语句来把这个事务回滚掉。
3.6 隐式提交
- 概述
当我们使用手动开启事务或者将自动提交关闭时,这个时候的提交权你以为是握在手中的,殊不知有几种情况(语句)还是会触发提交,即所谓的隐式提交
- 导致隐式提交的情况
- 定义或修改数据库对象的数据定义语言(Data definition language,缩写为: DDL )。当我们使用
ALTER USER 、 CREATE USER 、 DROP USER 、 GRANT 、 RENAME USER 、REVOKE 、 SETPASSWORD
等语句时也会隐式的提交前边语句所属于的事务- 隐式使用或修改 mysql 数据库中的表:当我们使用
ALTER USER 、 CREATE USER 、 DROP USER 、 GRANT 、 RENAME USER 、 REVOKE 、 SETPASSWORD
等语句时也会隐式的提交前边语句所属于的事务- 事务控制或关于锁定的语句:当我们在一个事务还没提交或者回滚时就又使用
START TRANSACTION 或者 BEGIN
语句开启了另一个事务时,会隐式的提交上一个事务;或者当前的autocommit
系统变量的值为OFF
,我们手动把它调为ON
时,也会隐式的提交前边语句所属的事务。或者使用LOCK TABLES 、 UNLOCK TABLES
等关于锁定的语句也会隐式的提交前边语句所属的事务。- 关于 MySQL 复制的一些语句使用
START SLAVE 、 STOP SLAVE 、 RESET SLAVE 、 CHANGE MASTER TO
等语句时也会隐式的提交前边语句所属的事务。- 其它的一些语句使用
ANALYZE TABLE 、 CACHE INDEX 、 CHECK TABLE 、 FLUSH 、 LOAD INDEX INTO CACHE 、 OPTIMIZETABLE 、 REPAIR TABLE 、 RESET
等语句也会隐式的提交前边语句所属的事务。
3.7 保存点
- 概述
使用数据库的人可能会在打完很多很多语句的时候突然想对某一句进行修改,这时如果直接回滚就有点一夜回到解放前的感觉。所以mysql提出保存点(savepoint),你可以分段进行标记或者很重要的操作的前后或者后面继续标记