MySQL 学习笔记——基础 TCL 事务控制语言
文章目录
一、准备知识
1、事务的概念
事务(Transaction)是由单独单元的一个或多个SQL语句组成,在这个单元中,每个SQL语句是相互依赖的。而整个单独单元作为一个不可分割的整体, 如果单元中某条SQL语句一旦执行失败或产生错误,整个单元将会回滚。所有影响的数据将会返回到事务开始之前的状态;如果单元中的所有SQL语句均执行成功,则事务被顺利执行。
2、事务的特点
- 原子性(atomicity):“原子”的本意是“不可再分”,事务的原子性表现为一个事务中涉及到的多个操作在逻辑上缺一不可。事务的原子性要求事务中的所有操作要么都执行,要么都不执行。
- 一致性(consistency):“一致”指的是数据的一致,具体是指:所有数据都处于满足业务规则的一致性状态。一致性原则要求:一个事务中不管涉及到多少个操作,都必须保证事务执行之前数据是正确的,事务执行之后数据仍然是正确的。如果一个事务在执行的过程中,其中某一个或某几个操作失败了,则必须将其他所有操作撤销,将数据恢复到事务执行之前的状态,这就是回滚。
- 隔离性(isolation):在应用程序实际运行过程中,事务往往是并发执行的,所以很有可能有许多事务同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。隔离性原则要求多个事务在并发执行过程中不会互相干扰。
- 持久性(durability):持久性原则要求事务执行完成后,对数据的修改永久的保存下来,不会因各种系统错误或其他意外情况而受到影响。通常情况下,事务对数据的修改应该被写入到持久化存储器中。
3、数据库事务并发产生的问题
假设有两个事务:Transaction01和Transaction02并发执行。
-
脏读:
[1] Transaction01 对将age从20修改为30。
[2] Transaction02 读取age值为30。
[3] Transaction01 发生回滚,将age值从30回滚为20。
[4] Transaction02 读取到的age值无效。
-
幻读
[1] Transaction01 读取Student表中的一些数据。
[2] Transaction02 向Student表插入一些数据。
[3] Transaction01 再次读取Student表,多了一些数据。
-
不可重复读
[1] Transaction01 读取age的值为20。
[2] Transaction02 将age的值该为30。
[3] Transaction01 再次读取age,发现两次读的值不一样。
4、事务的隔离级别
- 读未提交:READ UNCOMMITTED 允许Transaction01读取Transaction02未提交的数据。
- 读已提交:READ COMMITTED 要求Transaction01只能读取Transaction02已经提交的数据。
- 可重复读:REPEATABLE READ 确保Transaction01可以多次从一个字段中读取到相同的值,即Transaction01执行期间禁止其他事物对这个字段进行更新。
- 串行化:SERIALIZABLE 确保Transaction01可以多次从一个表中读取到相同的行,在Transaction01执行期间,禁止其他事物这个表进行添加、更新、删除操作。可以避免任何并发问题,但性能十分低下。
各种隔离级别能解决的并发问题:
脏读 | 幻读 | 不可重复读 | |
---|---|---|---|
读未提交 | ❌ | ❌ | ❌ |
读已提交 | ✔ | ❌ | ❌ |
可重复读 | ✔ | ✔ | ❌ |
串行化 | ✔ | ✔ | ✔ |
各种数据库对事物隔离级别的支持程度:
Oracle | MySQL | |
---|---|---|
读未提交 | ❌ | ✔ |
读已提交 | ✔ | ✔ |
可重复读 | ❌ | ✔(默认) |
串行化 | ✔ | ✔ |
5、MySQL对事务的支持情况
概念:在MySQL中的数据用不同的技术存储在文件或内从中。MySQL不同的存储引擎对事物的支持也不一样,InnoDB支持事物,MyISAM、MEMORY等不支持事物。可以通过show engines;
来查看MySQL支持的引擎。
+--------------------+---------+--------------+------+------------+
| Engine | Support | Transactions | XA | Savepoints |
+--------------------+---------+--------------+------+------------+
| MEMORY | YES | NO | NO | NO |
| MRG_MYISAM | YES | NO | NO | NO |
| CSV | YES | NO | NO | NO |
| FEDERATED | NO | NULL | NULL | NULL |
| PERFORMANCE_SCHEMA | YES | NO | NO | NO |
| MyISAM | YES | NO | NO | NO |
| InnoDB | DEFAULT | YES | YES | YES |
| BLACKHOLE | YES | NO | NO | NO |
| ARCHIVE | YES | NO | NO | NO |
+--------------------+---------+--------------+------+------------+
二、事务的使用
1、事物的分类
按操作分类:
- 隐式事物:事物没有明显的开启和结束的标记。比如insert、update、delete语句。
- 显示事物:事物具有明显的开启和结束的标记。前提是设置自动提交功能为禁用。
按事务理论分类:
-
扁平事务(Flat Transactions):在扁平事务中,所有操作都处于同一层次,其由事务开始,并同时隐式的设置一个保存点,由COMMIT或ROLLBACK结束,其间的操作是原子的,要么都执行,要么都回滚,回滚时回滚至开始设置的保存点。
-
带有保存点的扁平事务(Flat Transactions with Savepoints):与扁平事务相似,但是可以设置多个保存点。回滚时可以指定回滚至那个保存点,从事务开始至指定的保存点之间的操作保存但不提交,从ROLLBACK至指定的保存点之间的额操作回滚。带有保存点的扁平事务可以看做是对扁平事务的优化。
-
链事务(Chained Transactions):一个事务在提交的时候自动将上下文传给下一个事务,也就是说一个事务的提交和下一个事务的开始是原子性的,下一个事务可以看到上一个事务的处理结果。MySQL 的链式事务靠参数 completion_type 控制,并且回滚和提交的语句后面加上 work 关键词。
链事务与带有保存点的扁平事务不同的是,带有保存点的扁平事务能回滚到任意正确的保存点,而链事务中的回滚仅限当前事务,即只能恢复到最近的一个保存点,对于锁的处理,两者也不相同,锁事务在执行COMMIT后即释放了当前所持有的锁,而带有保存点的扁平事务不影响迄今为止所持有的锁。
-
嵌套事务(Nested Transactions):有多个 begin / commit / rollback 这样的事务块的事务,并且有父子关系。子事务的提交完成后不会真的提交,而是等到父事务提交才真正的提交。
-
分布式事务(Distributed Transactions):分布式事务用于在分布式系统中保证不同节点之间的数据一致性。分布式事务的实现有很多种,最具有代表性的是由Oracle Tuxedo系统提出的XA分布式事务协议。XA协议包含两阶段提交(2PC)和三阶段提交(3PC)两种实现,这里我们重点介绍两阶段提交的具体过程。
2、使用事物的步骤
-- 1、开启事物,以下两个语句都可以,使用一个即可。
set autocommit=0
start transaction;
-- 2、编写业务SQL
······
-- 3、提交事物或回滚事物
commit;
rollback;
3、保存点
-- 1、开启事物,以下两个语句都可以,使用一个即可。
set autocommit=0
start transaction;
-- 2、编写业务SQL
······
-- 3、设置保存点
savepoint a;
······
-- 4、回滚事物
rollback to a;
三、关于事物的一些问题
1、commit之后还能rollback吗?
答:不能,commit提交了事务就不能再rollback回滚了
2、执行的sql正确事物会自动提交吗?如果发生错误会自动回滚吗?
答:不能。如果事务中所有sql语句执行正确则需要自己手动提交commit;否则有任何一条执行错误,需要自己提交一条rollback,这时会回滚所有操作,而不是commit会给你自动判断和回滚。
3、在事务中创建或删除表,然后回滚会发生什么?
答:DDL直接触发隐式提交,任何事务回滚的前提是没有commit,隐式提交直接给你commit了,后续的rollback一点意义都没有。