数据库事务和隔离级别 MySQL

事务概述

事务是一个或一组sql语句组成的一个执行单元,这个执行单元要么全部执行成功要么全部执行失败。用于保证数据的完整性。

如账户转账,张三给李四转500,对应的sql语句应该是update张三的 余额-500,并且update李四的余额+500,如果先更新完张三的数据,然后出现了异常,导致李四的余额修改不了,那么就出现数据上的问题了,应该使用事务来解决这一问题,当中间出现异常后回滚,让张三的update失效;如果没有出现异常就提交事务

通过SHOW ENGINES;查看mysql中支持的存储引擎,注意只有innodb支持事务

事务的创建分为:

  • 隐式事务:事务没有明显的开启和结束的标记,如insert、update、delete语句执行时在默认情况下就是一个事务,因为默认是自动提交事务的,所有执行完后就立马自动提交事务了
  • 显式事务:事务具有明显的开启和结束的标记,前提是需要先设置自动提交事务为禁用,手动的提交事务或回滚事务

设置方法为: 

select @@autocommit;   #如果为1自动提交事务,为0需要手动提交事务
set autocommit=0;    #设置不自动提交事务

该设置只是针对当前会话有效,不是针对全局的。

使用事务的步骤:

  • 步骤一:开启事务

set autocommit=0;  

start transaction;   开启事务,可选的,不写也可以,因为关闭了自动提交事务后,默认就开启了事务,如果没有关闭就需要开启。 

  • 步骤二:编写事务中的sql语句
  • 步骤三:结束事务

commit;提交事务、rollback;回滚事务

事务的四大特性

事务的ACID属性为:

  • 原子性(Atomicity):原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
  • 一致性(Consistency):事务完成后,必须使所有的数据都保持一致状态,如转账的例子中双方的余额总和总是相同且正确的。
  • 隔离性(lsolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
  • 持久性(Durability):事务一旦提交或回滚,它对数据库中的数据的改变就是永久的。通过事务日志来保证,包括重做日志和回滚日志

并发事务问题

对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采取必要的隔离机制,就会导致各种并发问题:

问题描述
脏写一个事务修改了另一个事务未提交的数据,该事务可能被回滚。
脏读一个事务读到另外一个事务还没有提交的数据。
不可重复读一个事务先后读取同一条记录,但两次读取的数据不同,称之为不可重复读。
幻读

一个事务按照条件查询数据时,没有对应的数据行,但是在插入数据时,又

发现这行数据已经存在,好像出现了"幻影”。新插入的行为幻影记录

  • 脏写

当事务二修改一条数据还没提交时,如果事务一此时也修改了相同的数据,且立即提交了,此时事务二如果回滚,那么事务一的更新将不复存在,这种现象就为脏写。

  • 脏读

如下图,当事务二修改了id为1的数据后,事务一查询id为1的数据,查询的结果是修改后的数据,此时事务二可能会回滚事务,导致事务一查询的数据是一个脏数据,临时的数据。

  •  不可重复读

如下图,事务一中,两次查询相同id的结果是不同的,叫做不可重复读,侧重于在同一个事务中。

  • 幻读

如下图,当事务一第一次查询到没有id为1的数据时,准备插入前,事务二恰好插入了id为1的数据,且提交了事务,因为id是主键所以事务一会插入失败,此时因为解决了不可重复读的问题,事务一再次查询id为1的数据,还是查不到,然后就是插不进去,导致幻读。侧重于插入记录。

严重程度:脏写>脏读>不可重复读>幻读

脏写在所有隔离级别中都不会发生,如果某个事务想修改另一个事务还未提交的修改,就必须阻塞,等待那个事务结束。

事务的隔离级别

用于解决并发事务问题的。数据库提供的四种隔离级别:

隔离级别描述

READ UNCOMMITTED

(读未提交数据)

允许事务读取未被其他事务提交的变更,约束最小,速度最快

READ COMMITTED

(读已提交数据)

只允许事务读取被其他事务提交的变更,可以避免脏读

REPEATABLE READ

(可重复读)

确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,即使其它事务对以前的读取记录更新了,依然能读取到更新前的数据,可以避免脏读、不可重复读
SERIALIZABLE(串行化)确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,并发问题都能解决,性能低下

mysql默认是REPEATABLE READ,可以通过下面的命令查询当前的隔离级别

select @@transaction_isolation

通过下面的命令改变隔离级别,Session是会话级别的改变,Global是全局改变

set [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE]

演示:

用两个命令行打开不同的会话

1.演示在read uncommitted下的读脏数据,如下

 2.演示read committed

 如上发现read committed解决了读脏数据,但是在第3、4步的查询发现,在同一个事务中连续两次查询的同一列数据居然不相同了,出现不可重复读的问题。

3.演示repeatable read

 不可重复读解决了,但是幻读还存在,如下

通过手动加锁,可以解决幻读问题

 4.演示serializable,解决幻读问题

 该隔离级别性能比较低,但是涉及到了很多数据库锁的概念,可以深入了解一下

总结

隔离级别脏读不可重复读幻读
Read Committed
Read Uncommitted×
Repeatable Read××
Serializable×××

注意:事务隔离级别越高,数据越安全,但是性能越低。

  • 5
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值