事务及隔离级别


事务Transaction
SQL语句是我们给数据库发送了指令,让数据库帮我们做事情
1.事务可以理解为是让数据库做的事情
2.有些时候事情之内不止一条sql,存在多个组成单元
比如: 银行系统 转账 张三 100 --->李四
update atm set abalance = 原来-100 where aname = 张三;
update atm set abalance = 原来+100 where aname = 李四;
登录 查询余额 存款 取款 转账 开户 销户
.txt文件 I/O
缓存Map commit(); MVC分层思想 IO 缓存
3.一件事情中的所有操作应该是统一的
要么都成功,要么都失败
4.事务的本质
可以理解为
多线程并发操作同一张表格可能带来的安全问题
----------------------------------------------------------------------
事务的四大特性(ACID)
A:Atomicity---->原子性
一个事务中的所有操作是一个整体,不可再分
事务中的所有操作要么都成功,要么都失败
C:Consistency--->一致性
一个用户操作了数据,提交以后
另一个用户看到的数据与之前用户看到的效果是一致
*I:Isolation---->隔离性----->(事务隔离级别)
指的是多个用户并发访问数据库时
一个用户操作数据库,另一个用户不能有所干扰
多个用户之间的数据事务操作要互相隔离
D:Durability--->持久性
指的是一个用户操作数据的事务一旦被提交(缓存-->文件)
他对数据库底层真实的改变是永久性的 不可返回

----------------------------------------------------------------------
mysql数据库事务管理默认的效果可以更改
autocommit变量 = on;
show variables like '%commit%';
show variables like 'autocommit';
set autocommit = off; 设置自动提交关闭

1.开启一个事务
每一次执行的一条sql语句之前
mysql数据库都会默认的开启
begin; start transaction;
2.执行操作
insert update delete
select
可能不止一条语句
3.事务的处理
提交/回滚/保存还原点

commit   /  rollback   /   savepoint 还原点名 / rollback to 还原点名 ; 后边三个操作都在一个事务的过程中 事务一旦commit,则永久性改变,无法回滚等
mysql数据库会默认的执行提交事务

-----------------------------------------------------
事务的隔离性可能会产生多线程并发操作同一个数据库表格的问题
会带来数据的安全隐患
1.脏读
一个人读到了另外一个人还没有提交的数据
A B在操作同一张表格
A修改了数据,还没有提交,B读取到了
A不提交了,回滚回来,B刚刚读取到的那些数据就是无用的----脏数据
2.不可重复读
A B在操作同一个表格
A先读取了一些数据,读完之后B此时将数据做了修改/删除(commit了)
A再按照之前的条件重新读一遍,与第一次读取的不一致
3.幻读(虚读)
A B在操作同一个表格 A事务的正确业务逻辑应该是先查询是否存在这条记录,如果不存在,则插入

事务A-select * from emp where id=2 记录不存在,按理可以插入对吧,然后->事务B插入insert into emp values  where id=2 (这里如果不commit,则下一步操作会超时,如果commit则报错) ->事务A插入insert into emp values  where id=2(失败-有可能报主键或其它错误)->事务A查询select * from emp where id=2发现明明查询没有记录才插入的,但插入却始终不成功,仿佛幻觉了。

说明事务B影响到事务A的正常插入业务,导致事务A产生了不符合逻辑的情况,即明明是空记录,但是就是没法插入。

需要考虑事务的隔离级别
Serializable 最高 可以避免所有出现的问题 性能很慢
Repeatable Read 可重复读 (避免脏读,不可重复读)(有幻读的风险并非一定,20%的事务存在幻读的可能,80%的事务没有幻读的风险)
Read Committed 读已提交 (避免脏读)
Read UnCommitted 读取未提交 (所有效果均无法保证)

MySQL数据库提供默认隔离级别 Repeatable Read
Oracle数据库提供默认隔离级别 Read Committed

修改数据库中的隔离级别

一.5.7.20之后8.0版本前使用了transaction_isolation作为别名替代tx_isolation

命令格式:set [SESSION|GLOBAL] tx_isolation [Serializable] //session作用于当前会话,global作用于全局

set session tx_isolation ='read-uncommitted';

set global tx_isolation ='read-uncommitted';
如果不放心可以查看,清楚记得变量名,可以这样查隔离级别
select @@tx_isolation;或select @@transaction_isolation;

也可以模糊查询,show variables like '%isolation%';

二.8.0版本后,tx_isolation已经删除

命令格式:SET [SESSION|GLOBAL] transaction_isolation=[0|1|2|3];

实例:set session transaction_isolation=0;//这里可以是数字也可以是字符串

set session transaction_isolation='read-uncommitted';

0 --> 读未提交 (READ-UNCOMMITTED)

1 --> 读已提交 (READ-COMMITTED)

2 --> 可重复读 (REPEATABLE-READ)

3 --> 序列化  (SERIALIZABLE)

命令格式2(虽然不知道多一种写法的意义,但管它的呢):

set [session][global] transaction isolation level [Serializable] //session作用于当前会话,global作用于全局
实例:set gloabl transaction isolation level Serializable;

发现一个问题:set global transaction isolation level Serializable 或者set  transaction isolation level Serializable//执行成功但查询发现没生效

猜测带gloabl或默认 都是全局设置,全局设置都不生效?

实际是生效了但在当前会话看不到,重连再查看发现生效了的。

 注意:这些设置重启服务后都会恢复到默认状态

@阿拓老师在上 请受学生一拜

原文地址:https://www.cnblogs.com/hebiao/p/14211736.html