MySQL事务

MySQL事务

概述

事务是一组具有原子性的SQL语句,或是一个独立的工作单元

特性

一致性,原子性,隔离性,持久性 ---- ACID

查询与设置隔离级别

select @@tx_isolation;			   //查询当前的隔离级别
set session transaction isolation level read uncommitted/read committed/repeatable read/serializable			  	  //设置隔离级别
set autocommit = on/off;		   //事务的自动提交

事务启动方式

  1. begin/start transaction:这种启动方式并不会是在一开始就建立一致性视图,视图的建立是在第一个select语句查询的时候建立的
  2. start transaction with consistent snapshot : 执行这个语句的时候,一致性视图就建立了。

隔离性与隔离级别

当数据库上有多个事务同时执行的时候,就有可能出现脏读(dirty read)、不可重复读、幻读的问题,隔离级别就是用来解决这个问题

  1. 脏读:事务A读取到事务B还未提交的数据。(出现的隔离级别读未提交
  2. 不可重复读:事务A读到事务B修改后并提交的数据,可能会出现事务A在事务B修改提交之前的结果,与事务B提交之后读到的数据不同。(小明有3600元,正准备付款买单(事务A)的时候,小明的老婆将钱全部转走了(update),这时候付款sql读取到金额就变成0了)。(主要是指更新操作,总的记录条数没变化
  3. 幻读:幻读并不是指两次读取获取的结果集不同,幻读侧重于某一次的select操作得到的结果集,无法支撑后续的操作。如select查询某记录不存在,准备插入,但insert的时候又报错,提示已经存在,这就是出现了幻读。(总的记录数发生变化
级别名称 脏读 不可重复读 幻读
读未提交 0
读提交 1
可重复读 2
串行化 3

示例

脏读:

A客户端设置read uncommitted

事务A 事务B
begin begin
insert into s_users values(2,'demo',2000);
select * from s_users where id = 2; (能查询到id=2的数据)
rollback;
select * from s_users where id = 2; (为空)
select * from s_users where id = 2; (为空)

可重复读

将客户端A的隔离级别设置为read committed

事务A 事务B
begin beigin
update s_users set money=0 where id = 1;
select * from s_users where id = 1; (查询到money:1000)
commit;
select * from s_users where id = 1; (查询到money:0)

幻读

将客户端A的隔离级别设置为 repeatable read

事务A 事务B 事务C
start transaction with consistent snapshot
start transaction with consistent snapshot
update s_users set money = money + 800 where id = 1 (money=1800)
update s_users set money = money + 200 where id = 1 (money=2000)
select * from s_users where id =1 (1000)
commit
select * from s_users where id =1 (1000)
commit

解决方案

  1. RR级别下解决幻读,通过行锁来实现(X锁),当查询出来记录存在的时候就加X锁,如果不存在的时候就加gap锁(间隙锁),如select * from s_users for update; 来保证其它的事务无法来调用。在innodb中锁的都是索引,而非记录本身。
想生活,不想谋生
原文地址:https://www.cnblogs.com/Daneil/p/13823972.html