MySQL基础总结(四)
MySQL的事务控制和隔离机制
TCL (事务控制语言)
文章目录
MySQL的事务控制
事务的概念
一个或一组sql语句组成一个执行单元,这个执行单元要么全部执行,要么全部不执行
创建事务
- 隐式事务
概念 事务没有明显的开启和结束的标记
例如:insert,update,delete语句
可以查看一下,自动提交功能是否开启(默认ON,开启),如果开启,就表示默认一条语句就是一个事务
show variables like 'autocommit'
- 显式事务
如果不想让每一条语句成为一个事务,需要先关闭自动提交功能
set autocommit = 0;
注意
关闭事务的语句只针对当前回话有效,如果开启下一次会话,自动提交功能还是会默认开启
开启事务
#关闭自动提交
set autocommit=0;
#开启事务
start transaction; #其实这条语句可以省略,关闭自动提交之后会默认开启事务
...
事务中的sql语句
```
#提交事务
commit;
**注意 **
1. 只有DML(数据操作语言)和DQL(数据查询语言)才有事务的概念,即增删改查
2. DDL(数据定义语言),如alter,create等没有事务的概念
举例 小明给女朋友转账500元
#开启事务
set autocommit=0;
start transaction;
#小明账号-500,因为MySQL不能将同一个表查询出来的数据作为更新,所以需要简历一个中间表(看不懂下面的sql语句没事,知道是小明的账户-500就可以)
update 账户表 set 余额 = (
select (中间表.余额-500)
from(
select 余额
from 账户表
where 用户名='小明'
)中间表
)
where 用户名='小明';
#女朋友账号+500
update 账户表 set 余额 = (
select 中间表.余额
from(
select 余额
from 账户表
where 用户名='小明的女朋友'
) 中间表
)
where 用户名='小明的女朋友';
commit;
回滚事务
#关闭自动提交
set autocommit=0;
#开启事务
start transaction; #其实这条语句可以省略,关闭自动提交之后会默认开启事务
...
事务中的sql语句
```
### 回滚事务
rollback;
<br .>
MySQL的隔离机制
几种可能由于并发访问出现的问题
- 脏读
概念 对于两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段.
之后,若T2回滚,T1读取的内容就是临时且无效的.
- 不可重复读
概念 对于两个事务T1,T2, T1读取了一个字段,然后T2更新了该字段.
之后,T1再次读取同一个字段,值就不同了
- 幻读
概念 幻读:对于两个事务T1,T2,T1从一个表中读取了一个字段,然后T2在该表中插
入了一些新的行.之后,如果T1再次读取同一个表,就会多出几行
隔离级别
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交(read uncommitted) | √ | √ | √ |
读已提交(read commited) | × | √ | √ |
可重复读(repeatable read) | × | × | √ |
可串行化(serializable) | × | × | × |
- 查看默认隔离级别(默认是repeatable read )
5.x版本:
select @@tx_isolation;
8.x版本:
select @@transaction_isolation;
- 设置隔离级别
set session transaction isolation level <隔离级别>;
举例 将隔离级别设为最低
set session transaction isolation level uncommitted;
回滚点(savepoint)
用法 设置一个回滚点,当触发rollback
时,可以指定回滚到哪个回滚点的位置
语法
savepoint <回滚点名称>;
举例
#开启事务
set autocommit=0;
start transaction;
sql语句1;
sql语句2;
sql语句3;
savepoint a;
sql语句4;
sql语句5;
### 回滚事务
rollback to a; # 回滚到语句4之前
savepoint <回滚点名称>;
举例
#开启事务
set autocommit=0;
start transaction;
sql语句1;
sql语句2;
sql语句3;
savepoint a;
sql语句4;
sql语句5;
### 回滚事务
rollback to a; # 回滚到语句4之前