MySQL高级④(事务)

导读:本篇文章讲解 MySQL高级④(事务),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

也许你感觉自己的努力总是徒劳无功,但不必怀疑,你每天都离顶点更进一步。今天的你离顶点还遥遥无期。但你通过今天的努力,积蓄了明天勇攀高峰的力量。加油!

事务 是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。

事务简介

  • 数据库的事务(Transaction)是一种机制、一个操作序列,包含了一组数据库操作命令
  • 事务把所有的命令作为一个整体一起向系统提交或撤销操作请求,即这一组数据库命令要么同时成功,要么同时失败
  • 事务是一个不可分割的工作逻辑单元。

我们可以举一个例子更好的理解事务:
如下图有一张表

在这里插入图片描述

张三和李四账户中各有100块钱,现李四需要转换500块钱给张三,具体的转账操作为

  • 第一步:查询李四账户余额
  • 第二步:从李四账户金额 -500
  • 第三步:给张三账户金额 +500

现在假设在转账过程中第二步完成后出现了异常第三步没有执行,就会造成李四账户金额少了500,而张三金额并没有多500;这样的系统是有问题的。如果解决呢?使用事务可以解决上述问题

在这里插入图片描述

从上图可以看到在转账前开启事务,如果出现了异常回滚事务,三步正常执行就提交事务,这样就可以完美解决问题。

开启事务其实就是打一个标记,告诉数据库后边的执行都是一些临时的更改。只有当遇到提交事务的时候,才会成为一个持久化更改。而回滚事务就是撤销那些临时的操作回到开启事务之前的状态。

相应语法:
在这里插入图片描述

事务操作

我们将上述问题用事务去解决

  • 不加事务演示问题

    -- 转账操作
    -- 1. 查询李四账户金额是否大于500
    
    -- 2. 李四账户 -500
    UPDATE account set money = money - 500 where name = '李四';
    
    出现异常了...  -- 此处不是注释,在整体执行时会出问题,后面的sql则不执行
    -- 3. 张三账户 +500
    UPDATE account set money = money + 500 where name = '张三';
    

    整体执行结果肯定会出问题,我们查询账户表中数据,发现李四账户少了500。

    MySQL高级④(事务)

  • 添加事务sql如下:

    -- 开启事务
    BEGIN;
    -- 转账操作
    -- 1. 查询李四账户金额是否大于500
    
    -- 2. 李四账户 -500
    UPDATE account set money = money - 500 where name = '李四';
    
    出现异常了...  -- 此处不是注释,在整体执行时会出问题,后面的sql则不执行
    -- 3. 张三账户 +500
    UPDATE account set money = money + 500 where name = '张三';
    
    -- 提交事务
    COMMIT;
    
    -- 回滚事务
    ROLLBACK;
    

    上面sql中的执行成功进选择执行提交事务,而出现问题则执行回滚事务的语句。以后我们肯定不可能这样操作,而是在java中进行操作,在java中可以抓取异常,没出现异常提交事务,出现异常回滚事务。

事务四大特征(ACID)

  • 原子性(Atomicity): 事务是不可分割的最小操作单位,要么同时成功,要么同时失败

  • 一致性(Consistency) :事务完成时,必须使所有的数据都保持一致状态

    • 一致性是同时成功,同时失败的体现
  • 隔离性(Isolation) :数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。

  • 持久性(Durability) :事务一旦提交或回滚,它对数据库中的数据的改变就是永久的

隔离性的说明:
隔离性越强,操作越不可见,性能越低
隔离性约弱,操作越可见,性能越高
一般我们不会去改变事务的隔离性。
默认:当我们在MySQL中回滚或者提交之后,别人才能看到我们对应的修改

说明:
默认MySQL的事务是自动提交的,也就是说,当执行完一条DML语句时,MySQL会立即隐式的提交事务。
可以通过下面语句查询默认提交方式:

SELECT @@autocommit;

查询到的结果是1 则表示自动提交,结果是0表示手动提交。当然也可以通过下面语句修改提交方式

set @@autocommit = 0;

在这里插入图片描述

并发事务

问题 描述
脏读 一个事务读到另一个事务还没提交的数据
不可重复读 一个事务先后读取同一条记录,但两次读取的数据不同
幻读 一个事务按照条件查询数据时,没有对应的数据行,但是再插入数据时,又发现这行数据已经存在

我们来详细解释一下这几个概念:

脏读
在这里插入图片描述
比如说我们事务A和事务B在并发的对同一个数据库的同一个表进行操作。事务A先执行一个select,再执行update,就在事务A执行完select之后,事务B执行一个select拿到了事务A更新之后的数据,但是事务A此时是没有执行完的,并没有提交。这种情况就叫做脏读,我们可以说此时事务B拿到的是脏数据。

不可重复读
在这里插入图片描述
事务A先去执行一个select语句,在执行第二步操作的时候,B事务并发的进行了一个update操作,并且成功提交。而这时当事务A再次去查询id为1的数据的时候会发现数据不一样。这种现象称之为不可重复读。

幻读
在这里插入图片描述

事务A先开始查询id为1的数据,发现没有;这时候有一个并发事务B往数据库里面添加了一条id为1的数据,并且成功提交,也就是说此时数据库中已经有一条id为1的数据了,当事务A再去执行insert的时候因为主键冲突肯定不会成功的。此时事务A再去查询数据库仍然查不到id为1的数据(假设已经解决了重复读的问题),但是前面的插入操作确实失败了啊,好像出现了幻觉一般,这种情况就叫做幻读。

事务隔离级别

事务的隔离级别就是用来解决并发事务中出现的问题

并发事务隔离级别:

隔离级别 脏读 不可重复读 幻读
Read uncommitted
Read committed ×
Repeatable Read(默认) × ×
Serializable × × ×

MySQL的默认隔离级别是Repeatable Read,而Oracle的是Read committed

  • √表示在当前隔离级别下该问题会出现
  • Serializable 性能最低;Read uncommitted 性能最高,数据安全性最差

查看事务隔离级别:

SELECT @@TRANSACTION_ISOLATION

设置事务隔离级别:

SET [ SESSION | GLOBAL ] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE };

SESSION 是会话级别,表示只针对当前会话有效,GLOBAL 表示对所有会话有效

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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/122174.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!