目录
简要
手动事务使用案例
事务的特性
事务的隔离级别
脏读
不可重复读
幻读
查看事务隔离级别
设置隔离级别
mysq事务是自动提交的, 例如insert, update语句等
如下:
想要手动设置mysql事务就需要使用如下语句:
-- 关闭自动提交
set autocommit = 0;
autocommit默认值为1, 也就是默认开启自动事务
创建表格
create database if not exists db_transacton;
user db_transaction;
-- 创建用户表
create table userinfo(
id int primary key,
name varchar(20),
money double
);
插入数据:
insert into userinfo values(1,'zhangsan',1000);
insert into userinfo values(2,'lisi',1000);
设置手动提交事务:
set autocommit = 0;
在设置手动事务之前可以先查看autocommit的状态:
select @@autocommit;
-- 结果如下:
模拟账户转账:
begin; -- 首先要开启事务
update userinfo set money = money - 200 where id = 1; -- id == 1代表zhangsan
update userinfo set money = money + 200 where id = 2; -- id == 2代表lisi
-- 以下两个操作只能选择一个, 要么提交, 要么回滚
-- 执行完毕之后, 提交事务
commit;
-- 回滚事务
rollback
提交事务之后. 那么就相当于zhangsan向lisi转账成功, 回滚操作就相当于 提交的事务出现了问题,被重置, zhangshan和lisi都回到了交易之前的状态.
Isolate, 顾名思义就是将事务与另外一个事物隔离开, 为什么要隔离开呢? 如果一个事物正在操作的数据也被另外一个事务修改了, 最后执行结果可能无法达到预期, 如果没有隔离这两个事务, 那么后面还会导致很多问题出现.
这张图, 越往下面, 也就是越靠近序列化, 那么他的隔离级别就越高, 反之就越低, mysql的隔离级别默认是可重复度,
下面我们探究一个这四个事务隔离级别的作用:
- 读未提交( Read uncommitted )
一个事务可以读取另一个未提交事务的数据,最低级别,任何情况都无法保证,会造成脏读问题.
- 读已提交(Read committed)
一个事务要等另一个事务提交后才能读取数据,可避免脏读的发生,会造成不可重复读
- 可重复读(Repeatable read)
就是在开始读取数据(事务开启)时,不再允许修改操作,可避免脏读、不可重复读的发生但是会造成幻读。
- 串行(Serializable)
是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用
下面来分析一下什么叫做脏读, 不可重复读, 幻读!!
脏读又称无效数据的读出,是指在数据库访问中,事务T1将某一值修改,然后事务T2读取该值,此后T1因为某种原因撤销对该值的修改,这就导致了T2所读取到的数据是无效的,值得注意的是,脏读一般是针对于update操作的.
一个事务正在访问数据, 并且对数据做出了修改, 但是这种修改并没有提交到数据库中去, 也就是虽然修改了数据库的值, 但是并未提交事务, 没有提交事务就代表这个事物随时可能因为出现问题而回滚, 此外另外一个事务也访问这个数据, 然后使用了这个数据, 但是这个数据并未随着事务提交,而事后这个事务因为某些原因写入了错误的值而回滚, 这个时候另外一个事物读取到了这个错误的数据, 也就是脏数据, 依据这个脏数据做出的行为是不正确的. 他很有可能破坏事物的一致性. 那么这个事务读取这个错误的数据的行为就叫做脏读.
不可重复读,是指在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。
在一个事务内, 多次访问同一个数据, 但是同时另外一个事物也在访问同一数据并且要修改这个数据, 而且这个修改操作是穿插在这个事务多次访问之间的, 由于别的事务的修改, 那么会让第一个事务多次读取可能会存在读到的数据不一样的情况, 这样就发生了一个事务多次读取同一个数据, 但是读取到的结果是不一样的情况, 因此称为不可重复读.
指当事务不是独立执行时发生的一种现象.
例如, 事务T1对一个表中的数据进行了修改, 这个修改操作设计表中的全部数据行, 同时第二个事务T2也修改这个表中的数据, 这种修改时向表中插入一行新数据, 那么以后就会发生: 操作事务T1的用户发现表中还存在没有修改的数据行, 就好像发生了幻觉一样.
解决 幻读, 一般的方法是增加范围锁rangeS, 锁定检索范围为只读, 这样就避免了幻读.
show variables like '%isolation%'
其中Variable_name = transaction_isolation 的value值为 Repeatable-read, 也就是可重复读.
-- 设置读未提交
set session transaction isolation level read uncommitted;
-- 设置读已提交
set session transaction isolation level read committed;
-- 设置可重复读
set session transaction isolation level repeatable read;
-- 设置串行化
set session transaction isolation level serializable;