事务
基本概念
事务是一个完整的业务逻辑,是一个最小的工作单元,不可再分。
一个完整的业务逻辑包括一系列的操作,这些操作是整个业务逻辑中的最小单元,这些操作要么同时成功,要么同时失败。
由于只有DML语句中才会有事务的概念,因此事务只和insert
update
delete
语句有关。
说到底,说到本质上,一个事务其实就是多条DML语句同时成功,或者同时失败!
事务是怎么做到多条DML语句同时成功和同时失败的呢?
InnoDB存储引擎:提供一组用来记录事务性活动的日志文件
事务开启了:
insert
insert
insert
delete
update
update
update
事务结束了!
在事务的执行过程中,每一条DML的操作都会记录到“事务性活动的日志文件”中。在事务的执行过程中,我们可以提交事务,也可以回滚事务。
提交事务&回滚事务
-
提交事务
清空事务性活动的日志文件,将数据全部彻底持久化到数据库表中。
提交事务标志着,事务的结束。并且是一种全部成功的结束。 -
回滚事务
将之前所有的DML操作全部撤销,并且清空事务性活动的日志文件
回滚事务标志着,事务的结束。并且是一种全部失败的结束。
提交事务:commit; 语句
回滚事务:rollback; 语句(回滚永远都是只能回滚到上一次的提交点!)
在MySQL中,默认的事务行为是自动提交的,每次命令成功之后就会进行一次自动提交。
通过执行命令start transaction
关闭系统的自动提交。
回滚事务演示:
mysql> select * from t_student;
+----+-----------+------+
| no | name | cno |
+----+-----------+------+
| 1 | jack | 100 |
| 2 | lucy | 100 |
| 3 | lilei | 100 |
| 4 | hanmeimei | 100 |
| 5 | zhangsan | 101 |
| 6 | lisi | 101 |
| 7 | wangwu | 101 |
| 8 | zhaoliu | 101 |
+----+-----------+------+
8 rows in set (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.01 sec)
mysql> insert into t_student values(9,'ame',100);
Query OK, 1 row affected (0.01 sec)
mysql> insert into t_student values(10,'ame',100);
Query OK, 1 row affected (0.00 sec)
mysql> insert into t_student values(11,'ame',100);
Query OK, 1 row affected (0.00 sec)
mysql> select * from t_student;
+----+-----------+------+
| no | name | cno |
+----+-----------+------+
| 1 | jack | 100 |
| 2 | lucy | 100 |
| 3 | lilei | 100 |
| 4 | hanmeimei | 100 |
| 5 | zhangsan | 101 |
| 6 | lisi | 101 |
| 7 | wangwu | 101 |
| 8 | zhaoliu | 101 |
| 9 | ame | 100 |
| 10 | ame | 100 |
| 11 | ame | 100 |
+----+-----------+------+
11 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from t_student;
+----+-----------+------+
| no | name | cno |
+----+-----------+------+
| 1 | jack | 100 |
| 2 | lucy | 100 |
| 3 | lilei | 100 |
| 4 | hanmeimei | 100 |
| 5 | zhangsan | 101 |
| 6 | lisi | 101 |
| 7 | wangwu | 101 |
| 8 | zhaoliu | 101 |
+----+-----------+------+
8 rows in set (0.00 sec)
提交事务演示:
mysql> create table t_student(
-> no int primary key auto_increment,
-> name varchar(32)
-> );
Query OK, 0 rows affected (0.03 sec)
mysql> select * from t_student;
Empty set (0.00 sec)
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into t_student values(1,'jack');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t_student(name) values('nick');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t_student(name) values('nick');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t_student(name) values('nick');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t_student(name) values('nick');
Query OK, 1 row affected (0.00 sec)
mysql> insert into t_student(name) values('nick');
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
mysql> select * from t_student;
+----+------+
| no | name |
+----+------+
| 1 | jack |
| 2 | nick |
| 3 | nick |
| 4 | nick |
| 5 | nick |
| 6 | nick |
+----+------+
6 rows in set (0.00 sec)
mysql> rollback;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t_student;
+----+------+
| no | name |
+----+------+
| 1 | jack |
| 2 | nick |
| 3 | nick |
| 4 | nick |
| 5 | nick |
| 6 | nick |
+----+------+
6 rows in set (0.00 sec)
commit
操作实际上是将数据持久化的操作,在进行这个操作之前,仍在事务进行当作,数据仍然可以进行回滚,但是数据持久化之后就不能进行回滚了。
事务的四个特性
-
A : 原子性
事务是最小的工作单元,不可再分。
-
C: 一致性
所有事务要求,在同一个事务当中,所有操作必须同时成功,或者同时失败,保证数据的一致性。
-
I: 隔离性
不同的事务之间具有隔离,当两个事务想要操作同一张表的时候,他们之间的墙就会产生一定的隔离作用
-
D: 持久性
事务开始的标志一般是
start transaction
, 事务最终结束的标志是进行commit
操作,对数据进行了持久化,相当于将数据写进硬盘里。
事务的隔离性
事务和事务之间的隔离性具有四个不同的隔离级别:
- 读未提交
read uncommitted
- 事务A可以读取到事务B未提交的数据。
- 但是这种隔离级别会出现脏读现象,我们称读到脏数据
- 读已提交
read committed
- 事务A只能读取到事务B已经提交的数据。
- 不可重复读取数据:在事务开启之后,第一次读到的数据是3条,当前事务还没有结束,可能第二次再读取的时候,读到的数据是4条,3不等于4,称为不可重复读取。
- 可重复读
repeatable read
(mysql默认的隔离级别)- 两个事务对同一张表进行操作,不管对方是怎样操作的,各自只能看到自己事务中所做出的操作,即使事务B提交了,事务A也无法读取事务B修改后的数据。
- 序列化
serializable
(最高的隔离级别)- 效率最低,安全级别最高
- 这种隔离级别表现为事务排队,不能并发,事务A还在操作表1,事务B如果想要对表1进行操作,需要等事务A结束。
验证各种事务隔离级别
查看隔离级别:
查看系统隔离级别:select @@global.tx_isolation;
查看会话隔离级别(5.0以上版本):select @@tx_isolation;
查看会话隔离级别(8.0以上版本):select @@transaction_isolation;
mysql> select @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ | # mysql默认的隔离级别
+-------------------------+
设置隔离级别:
mysql> set global transaction isolation level read uncommitted;
mysql> set global transaction isolation level read committed;
mysql> set global transaction isolation level repeatable read;
mysql> set global transaction isolation level serializable;
设置完后记得重新登陆一下mysql
read uncommitted
验证
右边事务进行insert
后,左边事务是看的见的
read committed
验证
repeatable read
验证
右侧事务修改完之后,左侧事务也看不见修改。
serializable
验证
右边事务在等左边事务commit
,才会执行。