文章目录
1.事务的ACID4大特性
事务就是一组原子性的SQL查询,或者说一个独立的执行单元。如果数据库引擎可以成功的对数据库应用该组查询语句的全部语句,则执行改组查询,如果其中任意一条语句因为奔溃或者其他原因无法执行,那么所有查询都不会执行。即事务内的语句要么全部执行成功,要么全部执行失败。
事务同时具备:原子性(Atomicity),隔离性(lsolation),一致性(Consistency)和持久性(Durably)。
a.原子性(Atomicity)
一个事务必须视为一个不可分割的最小工作单元,整个事务中的所有操作,要么全部成功提交,要么全部失败回滚,对事物来说不能只执行其中一部分操作。
b.隔离性(Isolation)
通常来说一个事务在提交前所做的所有修改,对其他事务是不可见的。该功能通常是通过锁来实现的。
c.一致性(Consistency)
数据库总是从一个一致性状态转移到另一个一致性状态,即在事务还未提交前,事务所作的修改是不会保存到数据库中,在事务开始前和结束后,数据库的完整性约束没有被破坏。
对于转账场景,一致性表示每一次转账完成后,都需要保证整个系统的余额等于所有账户的收入减去所有账户的支出。
如果不遵循原子性,也就是如果小明向小强转账10元,但是只转了一半,小明账户少了10元,小强账户并没有增加,所以没有满足一致性了。
同样,如果不满足隔离性,也有可能导致破坏一致性。
所以说,数据库某些操作的原子性和隔离性都是保证一致性的一种手段,在操作执行完成后保证符合所有既定的约束则是一种结果。
实际上我们也可以对表建立约束来保证一致性。
d.持久性(Durablity)
一旦事务提交,则其所做的所有操作都会永久的保存到数据库中,即使系统奔溃,修改的数据也不会丢失。
2.事务的分类
a.扁平事务
在扁平事务中,所有操作处于同一状态,由began开始,由commit或rollback结束期间的操作是原子的,要么全部执行,要么全部失败。
扁平事务不能提交一部分操作或回滚一部分内容,只能全部成功或失败。
b.带有保存点的编排事务
在扁平事务的基础上,允许事务在执行的过程中回滚到同一事务的一个较早的状态,因为事务在执行过程中可能出现错误情况不会导致整个操作都失效,放弃整个事务的不合乎要求,开销太大。
保存点
MYSQL提出了一个保存点(英文: savepoint)的概念,就是在事务对应的数据库语句中打几个点,我们在调用ROLLBACK语句时可以指定会滚到哪个点,而不是回到最初的原点。定义保存点的语法如下:
SAVEPOINT 保存点名称;
当我们像回滚到某个保存点时,使用下面的语句:
ROLLBACK [WORK] TO [SAVEPOINT] 保存点名称;
不过如果ROLLBACK语句后边不跟随保存点名称的话,会直接回滚到事务执行之前的状态。
如果我们想删除某个保存点,可以使用这个语句:
RELEASE SAVEPOINT 保存点名称;
c.链事务
链事务是保存点模式的另一种实现,带保存点的扁平事务,当系统发生奔溃时,因为其保存点是容易丢失的,而非持久的,即进行恢复时事务要从开始重新执行,而不能从最近的一个保存点执行。
链事务的实现是:在提交一个事务时,释放不需要的数据对象,将必要的处理上下文隐式的传递给下一个要开始的事务。注意提交事务操作和开始下一个事务操作将合并为一个原子操作。就意味着下一个事务将看到上一个事务的结果,就好像在一个事务中进行一样。
d.嵌套事务
嵌套事务是一个层次结构框架,由一个顶层事务控制着各个层次的事务,顶层事务之下嵌套的事务被称为子事务,其控制每一个局部的变换,结构如下:
e. 分布式事务
分布式事务通常是一个分布式环境下运行的扁平事务,因此需要根据数据所在位置访问网络中的不同节点。
最常见的场景就是跨行转账,各银行都有自己的数据库。
3.事务的实现原理
数据库是通过日志来实现事务的,常见的日志有undo log ,redo log, 两种日志都能保证事务的特性。
redo log 称为重做日志,用来保证原子性和持久性.
undo log 用来保证redo一致性
redo 恢复提交事务修改的页操作,而undo 回滚到某个特定版本。二者记录的内容不同。redo记录的是物理日志,记录物理页的修改操作。而undo是逻辑日志,根据每行记录来记录。
a. redo
当事务提交时,必须先将该事务的重做日志写到重做日志文件中进行持久化,待事务的commit操作完成才算完成。
为了每次日志都写入重做日志文件,在每次重做日志缓冲写入重做日志文件后,InnoDB都需要调用一次fsync(同步内存中已修改的文件数据到磁盘)操作
b. undo
undo是逻辑日志,因此会将数据库逻辑恢复到原来的样子。所有修改逻辑都被取消了,但是数据结构和页结构本身在回滚后可能大不相同。因此在多用户并发系统中,一个事务修改当前页中的某几条记录,同时还有其他事务对同一页的几条记录进行修改,因此不能将一个页回滚到事务开始的样子,因为会影响其他正在进行的事务。
当InnoDB回滚时,它实际做的是与先前相反的工作。
- 对于每一个insert,InnoDB会完成一个delete
- 对于每一个delete,InnoDB会完成一个insert
- 对于每一个update,InnoDB会完成一个相反的update,将之前的修改的数据变成修改前的样子。
除了回滚操作,undo操作的另一个作用是MVCC,即当用户读取一行记录时,如果改行记录被其他事务占用,当前事务可以通过undo读取之前版本信息,以此实现非锁定读取。
4.事务的使用
a. 事务的开启
- begin [work]:开启一个事务,后面的work可有可无,开启事务后,后面可以写2若干条数据,这些数据都属于begin开启的事务.
- start transaction:与begin的功能相同。
b.提交事务
直接提交
- commit:提交当前的事务
手动终止事务
- rollback:回滚当前的操作,需要注意的是rollback语句是我们在写代码时手动回滚事务时使用,如果事务执行过程中错误而无法执行,会自动回滚。
自动提交
在默认情况下,如果我们不显示的使用begin或start transaction开启一个事务,那么每一条数据都算开启一个独立的事务,这种特性称为事务的自动提交。
如果我们想关闭自动提交功能,有以下两种方法:
- 显示的使用begin或start transaction开启一个事务,这样就会在本次事务提交或回滚前暂时关闭自动提交的功能。
- 把系统变量autocommit设置为OFF,像:set sutocommit=OFF;这样的话,我们写入多条语句就属于同一个事务了,直到我们显示的commit提交或使用rollback把事务回滚掉
隐式提交
当我们使用START TRANSACTION或者BEGIN语句开启了一个事务,或者把系统变量autocommit的值设置为OFF时,事务就不会进行自动提交,但是如果我们输入了某些语句之后就会悄悄的提交掉,就像我们输入了COMMIT语句了一样,这种因为某些特殊的语句而导致事务提交的情况称为隐式提交,这些会导致事务隐式提交的语句包括:
- 定义或修改数据库对象的数据定义语言( Data definition language,缩写为: DDL)。所谓的数据库对象,指的就是数据库、表、视图、存储过程等等这些东西。当我们使用CREATE、 ALTER、DROP等语句去修改这些所谓的数据库对象时,就会隐式的提交前边语句所属于的事务。
- 隐式使用或修改mysql数据库中的表:当我们使用ALTER USER、 CREATE USER、 DROP USER、GRANT、 RENAME USER、 SET PASSWORD等语句时也会隐式的提交前边语句所属于的事务。
- 事务控制或关于锁定的语句:当我们在一个事务还没提交或者回滚时就又使用START
TRANSACTION或者BEGIN语句开启了另一个事务时,会隐式的提交上一个事务。或者当前的autocommit系统变量的值为OFF,我们手动把它调为ON时,也会隐式的提交前边语句所属的事务。或者使用LOCK TABLES、 UNLOCK TABLES等关于锁定的语句也会隐式的提交前边语句所属的事务。 - 加载数据的语句:比如我们使用LOAD DATA语句来批量往数据库中导入数据时,也会隐式的提交前边语句所属的事务。
- 其它的一些语句:使用ANALYZE TABLE、 CACHE INDEX、 CHECK TABLE、 FLUSH、 LOAD,INDEX INTO CACHE、 OPTIMIZE TABLE、 REPAIR TABLE、 RESET等语句也会隐式的提交前边语句所属的事务
5.事务的隔离级别
- READ UNCOMMITED
- REAN COMMITED
- REPEATABLE READ
- SERIALIZABLE
隔离级别要将的的东西比较多后面再开一章讲
【MySql】- 2.MySQL的事务2-隔离级别