• 6、mysql事务


    1、mysql事务

    —mysql中,事务其实是一个最小的不可分割的工作单元。事务能够保证一个业务的完整性,例如:银行存款:

    a  - >    -100

    >update user set money = money -100 where name ="a";

    b - >    +100

    >update user set money = money +100 where name ="b";

    —实际程序中,如果一条语句执行成功了,而另一条语句执行失败,那么麻烦就大了……

    >update user set money = money -100 where name ="a";

    >update user set money = money +100 where name ="b";

    多条sql语句有要求要么就同时成功,要么就同时失败

    2、mysql中如何控制事务?

    ——查看事务状态(开启还是关闭)

        >select @@autocommit;


     

    上图‘1’表示mysql 默认是开启事务的(自动提交)

    ——默认事务开启是什么?

        当我们在执行sql语句时,效果会立即体现出来,且不能回滚(回滚后面会讲到)

    ——下面用一个案例来解释mysql事务:

    (1)创建新的数据库名为bank

        >create database bank;

    (2)在bank数据库中创建新的表名为user

        > create table user(

        -> id int primary key,

        -> name varchar(20),

        -> money int);

    (3)往user表中添加数据

        > insert into user values(1,'a',1000);

    (4)查看是否添加成功

        >select * from user;


     

    (5)回滚(就是撤销sql语句执行的效果)

        >rollback;


     

    (6)验证sql的语句执行的效果是否撤销

        >select * from user;


     

    (7)如果想要让回滚有效的话需要关闭事务(关闭mysql的自动提交)

        >set @@autocommit=0;

        >select @@autocommit;


     

    验证回滚:

        <a>再插入一条数据

            >insert into user values(2,'b',1000);

        <b>查看此时的user表

            >select * from user;


     

    【注】上述的表其实是虚拟的如果现在回滚就可以实现撤销

            <c>回滚

                >rollback;

            <d>查看

                >select * from user;


     

            <e>重复上述操作


     

            <f>由于关闭了自动提交功能,现在手动提交

                >commit;

             <g>再回滚查看表(显然回滚失效了)


     

    【总结】

    事务:

    ——自动提交:@@autocommit=1;

    ——手动提交:commit;

    ——回滚:rollback;

    转账:

        >update user set money = money -100 where name ="a";

        >update user set money = money +100 where name ="b";

    如果转账失败(同时失败)

    可以用回滚实现撤销

        >rollback;

    ——实现:


     

     

    (8)小结

    ——手动开启一个事务的方式:(在这里说一下不知道是不是版本的问题我的电脑上试过了 <2>begin;与 <3>start transaction;是改不了的建议使用第一个,如果您跟我一样,后边关于设置手动事务的都用第一个方法)

        <1>set @@autocommit =0;

        <2>begin;

        <3>start transaction;

    具体验证可以参照(7)的流程哦

    ——关闭手动开启恢复自动开启

           >set @@autocommit =1;

    ——查看事务的状态

            >select @@autocommit;

    ——回滚

            >rollback;

    ——提交

            >commit;

    【总结】

    综上:我们学到了,事务是以两种方式存在的:一是手动开启事务,二是默认(自动)开启事务

    手动开启事务给我们提供了一个修改的机会,如果操作失败的话可以通过回滚,实现修改,如果操作成功可以手动提交(commit)增加数据的安全性哦

    3、事务的四大特征

    A    原子性:事务是最小的单位,不可以再进行分割了

    C    一致性:事务要求同一事务中的sql语句,必须保证同时成功或者同时失败

    I     隔离性:事务1与事务2之间具有隔离性(后面详解)

    D    持久性:事务一旦结束(commit),就不可以返回(rollback)

    4、事务的隔离性

    (1)read uncommitted        读未提交的

    (2)read committed            读已提交的

    (3)repeatable  read           可以重复读

    (4)serializable                    串行化


    (1)read uncommitted        读未提交的

    【定义】现有事务a和事务b,a事务对数据进行操作,在操作过程中,事务没有被提交,但是b可以看见a操作的结果

    <a>在bank中的表user中插入两条数据

        >insert into user values(3,'小明',1000);

        >insert into user values(4,'淘宝店',1000);


    【拓展】

    ——如何查看数据库的隔离级别

    mysql 8.0

    <a>系统级别的

        > select @@global.transaction_isolation;(如下图:mysql默认的系统隔离级别)


     

    <b>会话级别的

        > select @@transaction_isolation;

    mysql 5.x

    <a>系统级别的

    > select @@global.tx_isolation;

    <b>会话级别的

    > select @@tx_isolation;

    ——如何修改数据库的隔离级别?

        >set global transaction isolation level read uncommitted;

    查看修改结果:


     

    模拟脏读:上述已经添加了小明和淘宝店两个用户

    小明现要在淘宝买一双800元的鞋子,开始付钱

    小明    ——>成都       

    淘宝    ——>广州

    <a>开启手动开启事务

        >set autocmmit =0;

    <b>转账

        >update user set money = money -800 where name ='小明';

        >update user set money = money +800 where name ='淘宝店';

    <c>小明查看转账记录,并通知发货


     

    <d>淘宝店在广州查账(这里模拟的话可以再打开一个终端操作),到账欣喜(准备晚上请女朋友吃大餐),并发货


     

    <e>晚上吃饭结账1800,刷卡显示余额不足(先自己想想为什么哦),气急败坏,再次查账:


     

    <f>原来小明是个黑客,利用所学知识,回滚了(查账,欣喜又赚了一笔)


     

    【总结】在事务隔离性为  read uncommitted  ( 读未提交的)情况下:

    两个不同的地方,都在进行操作,如果事务a开启之后,他的数据可以被其他事务读取到

    这样就会像上述实例那样,出现脏读;

    脏读:一个事务读到了另外一个事务并没有提交的数据,这就叫做脏读

    当然实际开发中是不允许的

    (2)read committed            读已提交的

    ——修改事务隔离性

        >set global transaction isolation level read committed;

    实例:bank数据库,user表

    <a>小张:银行会计    需要报表:

        >begin;

        > select * from user;


     

    <b>小张出去上厕所去了,这时小王又在另一台电脑上开了一个账户

        > insert into user values(5,'c',100);

    <c>小张这时回来了,计算money平均值

        >select avg(money) from user;


     

    <d>很纳闷,怎么变少了,看着报表陷入沉思(这个实例虽然有点脑残,主要是理解这个事务隔离性哈)

    【总结】在事务隔离性为    read committed  (读已提交的)

    虽然可以读到另外一个数据提交的数据(不会出现脏读),但还是会出现问题就是

    读取同一个表,发现前后数据不一致,

    不可重复读现象: read committed 

    (3)repeatable read       可以重复读

    先对之前的隔离性做更改

        >set global transaction isolation level repeatable read;

    ——那么在这种情况下又会发生什么事情呢?

    【实例】

    张全蛋—北京(是repeatable read    事务隔离的情况下)

    <a>开启手动事务服务

        >set autocommit =0;

    <b>开通一个账户

        >insert into user values(6,'d',1000);

    <d>查看

        >select * from user;


     

    王尼玛—上海(默认事务隔离性的情况下)

    <a>开启手动事务服务

    >set autocommit =0;

    <b>也想开通账户,开通前先查看(注意模拟的话可以再打开一个终端)

        >select * from user;

    <c>因其只开通了5个,于是想要继续开通6

        > insert into user values(6,'d',1000);

    结果:


     

    <d>很奇怪,为啥不行的,明明没有6,陷入沉思

    <e>试试创建id=7,很成功

        >insert into user values(7,'d',100);

    <f>查看

        >select * from user;


     

    <g>很奇怪,创建id=6为啥就是不行呢,陷入沉思……(我告诉你这叫做幻读,嘿嘿)

    【总结】这种现象叫做幻读

    幻读:事务a和事务b同时操作一样表,事务a提交数据也不会被事务b读到,就会造成幻读

    (4)serializable                    串行化

    ——先更改事务隔离性

        >set global transaction isolation level serializable;

    【实例】

    ——张全蛋—成都

        >set autocommit =0;

        开户并提交

        >insert into user values(7,'赵铁柱',1000);

        >commit;

    ——王尼玛—北京

        >set autocommit =0;

        查看表,看到了赵铁柱

        >select * from user;


     

    ——张全蛋—成都

    又开了一个户

      >insert into user values(8,'王小花',1000);

    但是进入等待状态了,卡住了

    这时——王尼玛—北京上述有说到正在看表,此时马上提交:commit,张全蛋那立刻就不卡了

    这就是串行化

    【总结】

    当user表被另外一个事务操作的时候,其他事务里面的写操作,是不可以进行的

    进入排队状态(串行化),直到王尼玛不进行事务操作了(输入commit结束事务之后),张全蛋这个写入操作才会执行(在没有超时的情况下)

    ——串行化带来的问题:性能太差

    read uncommitted  > read committed   > repeatable  read   >  serializable     

    即隔离级别越高,性能越差

    mysql默认的级别是    repeatable  read

                      关注个人公众号,有福利哦……

  • 相关阅读:
    CentOS Linux使用crontab运行定时任务详解
    pycharm自定义代码片段
    迭代器:斐波那契数列
    mysql复习-来源考试
    复杂和遗留的数据库schema
    ubuntu系统AndroidStudio修改内存大小
    Hibernate设置时间戳的默认值和更新时间的自动更新
    Android 自定义view --圆形百分比(进度条)
    MYSQL 更新时间自动同步与创建时间默认值共存问题
    ubuntu virtualbox xp无声音解决
  • 原文地址:https://www.cnblogs.com/guo-2020/p/12315179.html
Copyright © 2020-2023  润新知