MySQL 事务及事务的隔离级别之脏读、不可重复读、幻读

谁都会走 提交于 2019-11-30 19:15:30

一、事务

1、事务的应用场景
在实际开发过程中,如果操作转账,往往要多次访问数据库才能完成。转账是一个用户扣钱,另一个用户加钱。如果有其中一条 SQL 语句出现异常,这条SQL语句就可能执行失败。
事务执行是一个整体,所有的SQL语句都必须执行成功,如果有其中一条 SQL 语句出现异常,则所有的 SQL都要回滚,整个业务执行失败。

2、案例:模拟 加藤鹰 给 泷泽萝拉 转账500元
在这里插入图片描述
转账操作需要执行两条语句,则:
在这里插入图片描述
如果执行完第一条语句后,服务器崩溃了,那就造成了 加藤鹰的余额减少了500,而泷泽萝拉的余额并没有增加500。
只有当两条语句都执行成功的话,转账才算成功,这就用到了事务

3、手动提交事务
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、自动提交事务

在这里插入图片描述
在这里插入图片描述

二、事务的原理

1、事务开启之后,所有的操作都会临时保存到事务日志中,事务日志只有在得到 commit 命令后才会同步到数据表中,其他任何情况都会情况日志(rollback 断开连接)

2、原理图
在这里插入图片描述
3、事务的步骤

  • 客户端连接数据库服务器,创建连接时创建此用户的临时日志文件
  • 开启事务以后,所有的操作都会先写入到临时日志文件中
  • 所有的查询操作都从表中查询,但会经过日志文件加工后才返回
  • 如果事务提交则将日志文件中的数据写到表中,否则情况日志文件

三、事务的回滚点

1、回滚点
在某些成功的操作完成后,后续的操作又可能成功有可能失败,但是不管成功还是失败,前面的操作都已经成功,可以在当前成功的位置设置一个回滚点,可以供后续失败操作返回到该位置,而不是返回所有操作,这个点称为回滚点

2、回滚点的操作语句
在这里插入图片描述
在这里插入图片描述
3、回滚总结
设置回滚点可以让我们在失败的时候回到回滚点,而不是回到事务开启的时候

四、事务的隔离级别

在这里插入图片描述
单词

  • isolation :隔离
  • transaction :交易、业务、事务
  • level :级别、数量

隔离级别的命令

  • 查询隔离级别:select @@tx_isolation;
  • 设置全局隔离级别:set global transaction isolation level 级别字符串;
  • 设置当前隔离级别:set session transaction isolation level 级别字符串;

在这里插入图片描述

1、脏读
以 account 表为例
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

A窗口开启事务,进行操作数据后,在没有提交事务的时候,B窗口是可以看到A操作的数据的。由此可见,脏读的隔离安全性最低。
解决脏读的问题:将全局隔离级别设置为:read committed
在这里插入图片描述
在这里插入图片描述
总结:read committed 的方式可以避免脏读的发生

2、不可重复读
在这里插入图片描述
在这里插入图片描述
在 B 窗口第二次查看数据发现与第一次查看的数据不同,对于B窗口来说,不知道那次的数据是正确的。
如果要解决这个问题,就要解决不可重复的问题

在这里插入图片描述
在这里插入图片描述
结论:同一个事务中,为了保证数据多次查询一致,必须使用 repeatable read隔离级别

3、幻读
在这里插入图片描述
将事务的隔离级别设置到最高 serializable来阻挡幻读的发生
在这里插入图片描述

  • 当在A窗口 commit 提交事务后,B窗口才会执行插入
  • 这时在A窗口执行 select count(*) from account;发现数据没变,还是2
  • 接着在B窗口执行 commit 提交事务后,在次A窗口执行 select count(*) from account;才能看到最新的数据,是3

总结:使用serializable 隔离级别时,一个事务没有执行完,其他事务的SQL语句执行不了

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!