打算提升sql技能的,可以加我微信itsoku,带你成为sql高手。
这是Mysql系列第14篇。
环境:mysql5.7.25,cmd命令中进行演示。
开发过程中,会经常用到数据库事务,所以本章非常重要。
本篇内容
- 什么是事务,它有什么用?
- 事务的几个特性
- 事务常见操作指令详解
- 事务的隔离级别详解
- 脏读、不可重复读、可重复读、幻读详解
- 演示各种隔离级别产生的现象
- 关于隔离级别的选择
什么是事务?
数据库中的事务是指对数据库执行一批操作,这些操作最终要么全部执行成功,要么全部失败,不会存在部分成功的情况。
举个例子
比如A用户给B用户转账100操作,过程如下:
1.从A账户扣1002.给B账户加100
如果在事务的支持下,上面最终只有2种结果:
- 操作成功:A账户减少100;B账户增加100
- 操作失败:A、B两个账户都没有发生变化
如果没有事务的支持,可能出现错:A账户减少了100,此时系统挂了,导致B账户没有加上100,而A账户凭空少了100。
事务的几个特性(ACID)
原子性(Atomicity)
事务的整个过程如原子操作一样,最终要么全部成功,或者全部失败,这个原子性是从最终结果来看的,从最终结果来看这个过程是不可分割的。
一致性(Consistency)
一个事务必须使数据库从一个一致性状态变换到另一个一致性状态。
首先回顾一下一致性的定义。所谓一致性,指的是数据处于一种有意义的状态,这种状态是语义上的而不是语法上的。最常见的例子是转帐。例如从帐户A转一笔钱到帐户B上,如果帐户A上的钱减少了,而帐户B上的钱却没有增加,那么我们认为此时数据处于不一致的状态。
从这段话的理解来看,所谓一致性,即,从实际的业务逻辑上来说,最终结果是对的、是跟程序员的所期望的结果完全符合的
隔离性(Isolation)
一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(Durability)
一个事务一旦提交,他对数据库中数据的改变就应该是永久性的。当事务提交之后,数据会持久化到硬盘,修改是永久性的。
Mysql中事务操作
mysql中事务默认是隐式事务,执行insert、update、delete操作的时候,数据库自动开启事务、提交或回滚事务。
是否开启隐式事务是由变量autocommit控制的。
所以事务分为隐式事务和显式事务。
隐式事务
事务自动开启、提交或回滚,比如insert、update、delete语句,事务的开启、提交或回滚由mysql内部自动控制的。
查看变量autocommit是否开启了自动提交
mysql> show variables like 'autocommit';+---------------+-------+| Variable_name | Value |+---------------+-------+| autocommit | ON |+---------------+-------+1 row in set, 1 warning (0.00 sec)
autocommit为ON表示开启了自动提交。
显式事务
事务需要手动开启、提交或回滚,由开发者自己控制。
2种方式手动控制事务:
方式1:
语法:
//设置不自动提交事务set autocommit=0;//执行事务操作commit|rollback;
示例1:提交事务操作,如下:
mysql> create table test1 (a int);Query OK, 0 rows affected (0.01 sec)mysql> select * from test1;Empty set (0.00 sec)mysql> set autocommit=0;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values(1);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a |+------+| 1 |+------+1 row in set (0.00 sec)
示例2:回滚事务操作,如下:
mysql> set autocommit=0;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values(2);Query OK, 1 row affected (0.00 sec)mysql> rollback;Query OK, 0 rows affected (0.00 sec)mysql> select * from test1;+------+| a |+------+| 1 |+------+1 row in set (0.00 sec)
可以看到上面数据回滚了。
我们把autocommit还原回去:
mysql> set autocommit=1;Query OK, 0 rows affected (0.00 sec)
方式2:
语法:
start transaction;//开启事务//执行事务操作commit|rollback;
示例1:提交事务操作,如下:
mysql> select * from test1;+------+| a |+------+| 1 |+------+1 row in set (0.00 sec)mysql> start transaction;Query OK, 0 rows affected (0.00 sec)mysql> insert into test1 values (2);Query OK, 1 row affected (0.00 sec)mysql> insert into test1 values (3);Query OK, 1 row affected (0.00 sec)mysql> commit;Query OK, 0 rows affect