Mysql之事务

Mysql之事务_第1张图片

基本概念

事务就是一组增删改(dml)语句,该组语句要么全部成功,要么全部失败,比如可以用来处理转账,下面有一个图来帮助理解
Mysql之事务_第2张图片

关于保存点和回滚

Mysql之事务_第3张图片
我们事务操作的基本流程
就是
开启事务-设置保存点-回滚(或者直接提交)
比如上图,你在10.00,11.00设置保存点
12.00,你发现11.00到12.00的操作有误
你可以回滚到11.00那个保存点b,或者直接回滚到10.00就是第一个图的退回全部事务-这样对应时间段的操作就不会生效

事务操作

# 演示事务几个操作
# 先建表
CREATE TABLE t27(
	id INT,
	`name` VARCHAR(32));
# 开启一个事务
START TRANSACTION
# 设置保存点
SAVEPOINT a
# 执行dml操作
INSERT INTO t27
	VALUES(100,'tom');
SELECT * FROM t27;
# 再设置一个保存点
SAVEPOINT b
# 执行dml操作
INSERT INTO t27
	VALUES(200,'jack');
# 回退到b
ROLLBACK TO b -- 会发现t27回退到执行到b保存点的状态(没有200,jack)
# 继续回退到a
ROLLBACK TO a -- 这个再执行的话,100,tom也没了

ROLLBACK -- 如果这样写就是回退到事务最开始的一个状态

Mysql之事务_第4张图片

注意:1.当我们提交了(执行完commit操作),就不能回退了,会自动删除所有保存点
2.你不能从一个靠前的保存点回退到靠后保存点,比如你回退到了a点,这个操作会删除所有,从你开始回退那个点到a点中间的所有保存点,就是b点会被删除
3.你没有执行commit操作前,其他连接可能查不到(为什么是可能-涉及到下面的隔离级别)数据的变化,只有commit执行完,数据生效,其他连接肯定可以查看

细节

Mysql之事务_第5张图片
1.dml操作前没开启事务执行dml语句就自动提交,不能回顾
2.就是开启事务默认就开始事务有一个保存点,你可以通过ROLLBACK来返回事务最开始的状态
3.可以建立多个保存点
4.没有提交前可以回退-回退相关可以上面高亮字有比较详细解释
5.关于引擎最好用innodb
6.两种方式都可以开启事务

事务隔离级别

Mysql之事务_第6张图片
隔离就是针对事务的隔离,相当于事务的一个属性

关于隔离级别的三个问题

关于脏读,不可重复读和幻读
Mysql之事务_第7张图片

事务1和事务2
1.脏读
事务1未提交其作出的dml操作,事务2SELECT的结果却是事务1操作后的,就叫脏读
2.不可重复读-重在修改删除
和脏读不同,事务2进行表的查询,而事务1做dml操作,事务2在事务1提交前查询
和事务2在事务1提交后
查询的结果不同(事务2查询到事务1修改后的结果)
你可能认为这样是对的,然而比如你事务2在10.00连接数据库统计10.00前是数据
你统计到一半,嘎,事务1操作提交,事务2看到10.01进行修改的数据
本身就是想统计10.00前的数据,所以就不合理
3.幻读-重在插入
就类似于不可重复读
最大的不同就是,我们幻读是插入操作
不可重复读是修改和删除操作

1.未提交——>脏读 2. 删除、修改——>不可重复读 3.插入——> 幻读
Mysql之事务_第8张图片
注意:要先改隔离级别,再启动事务,先启动事务再改的话,开启的事务还是原来的隔离级别

脏读

# 演示事务隔离级别
# 1.先开mysql的两个控制台1和2
# 2.查看当前mysql的隔离级别
SELECT @@tx_isolation;
# 对应的隔离级别-可重复读(1和2)
#mysql> SELECT @@tx_isolation;
#+-----------------+
#| @@tx_isolation  |
#+-----------------+
#| REPEATABLE-READ |
#+-----------------+

# 3.选择数据库,创建表(控制台1)
USE db02;
CREATE TABLE `account`(
	id INT,
	`name` VARCHAR(32),
	money INT);
# 控制台2也连接一下db02数据库

# 4.把控制台2的隔离级别设置成READ uncommitted - 读不提交的
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
# 5.开启事务(1和2)
START TRANSACTION; -- 控制台一定要+分号
# 6.控制台1随便添加一条记录(100,'tom',1000)别提交

# 7.在控制台2查询该表,看变化,可以查询到添加的数据(一定要先改隔离级别)
这就是我们所谓的脏读现象,可以读到还没有提交的数据

控制台1
Mysql之事务_第9张图片
控制台2
Mysql之事务_第10张图片

不可重复读

# 控制台2隔离级别改成READ COMMITTED,再开启事务
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
# 这样就不会读取到没有提交的
# 然后控制台1该所有人工资为3000
update account set money=3000;
# 控制台2查询一下account表,查询不到改变
# 控制台1提交事务
commit;
# 再在控制台2查,发现改变了
这就是不可重复读

控制台1
Mysql之事务_第11张图片
控制台2
Mysql之事务_第12张图片

幻读

幻读的话
和上面其实差不多
就是删改操作变成添加数据操作

控制台1添加一个数据后提交
控制台2再次查询观察到添加数据后的改变

控制台1
Mysql之事务_第13张图片
控制台2
Mysql之事务_第14张图片

隔离级别本身

Mysql之事务_第15张图片
其实就这几个隔离级别,前面的话主要说了
前两种 READ UNCOMMITTED和READ COMMITTED,不再次说明了
其实后两种其实就是一个锁的问题(都不会出现本事务读到其他事务操作的信息!)就读你开启事务时间段是对应数据库的信息

可重复读


控制台1更改且提交
控制台2查询,查询结果不变,不会查询到命令行1的更改

控制台1
Mysql之事务_第16张图片
控制台2
Mysql之事务_第17张图片

可串行化

!!!
锁!
这个锁的作用,就是当有别的事务在操作我们要查询的表的时候
你的查询会等待对应操作事务结束后才显示结果

控制台A
Mysql之事务_第18张图片
我先不进行提交操作
控制台2
Mysql之事务_第19张图片
尽管我按下了回车也没有显示,只有等控制台1提交后才显示,但是不会显示控制台1改变的结果
然后再控制台1按下回车,控制台2就会直接显示出来
这也就是锁的作用
Mysql之事务_第20张图片

一些具体指令

Mysql之事务_第21张图片

查看事务隔离级别-查看单个用户的
1.SELECT @@tx_isolation;
查看系统隔离级别-所有用户登陆的默认隔离级别
2.SELECT @@global.tx_isolation;
设置当前事务隔离级别
3.SET SESSION TRANSACTION LEVEL 隔离级别;-后面写你想设置的隔离级别,上面的隔离级别图片有
设置系统当前隔离级别
4.SET GLOBAL TRANSACTION ISOLATION LEVEL 隔离级别; 同上
	关于特殊项目需要修改隔离级别
可以自己查一下,主要是修改my.ini文件的操作

事务acid

Mysql之事务_第22张图片
就是一些特性,一般是可以从上面的学习中总结出来
这里列一下

你可能感兴趣的:(Mysql,mysql,数据库,java)