• mysql事务


    一、什么是事务

    • 不可分割的操作,假设该操作有ABCD四个步骤组成,则ABCD四个步骤都成功完成,则认为事务成功;ABCD任意一个步骤失败,则事务失败

    • 每条sql语句都是一个事务

    • 事务只对DML语句有效,对DQL语句无效


    二、事务的ACID

    • 原子性:指事务包含的所有操作要么全部成功,要么全部失败回滚

    • 一致性:指事务必须使数据库从一个一致性状态换到另一个一致性状态,即事务执行之前和之后都必须处于一致性状态;一个商品出库,仓库减1,对应用户的购物车加1

    • 隔离性:隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务干扰,多个并发事务之间要相互隔离

    • 持久性:指一个事务一旦提交了,就不能再回滚了,已经把数据保存到数据库当中了。


    三、事务的使用

    开启事务: start transaction;

    提交事务: commit 所有语句全部执行完毕,没有发生异常,提交事务,更新到数据库当中。

    回滚事务: rollback 如果遇到突发情况,撤销执行的 sql 语句。

    1.提交事务

    建两张表,模拟两个账户:

    create table zs_account(
    	name VARCHAR(50),
    	money DECIMAL
    );
    
    create table ls_account(
    	name VARCHAR(50),
    	money DECIMAL
    );
    

    cmd:
    C:Usersgd>mysql -u root -p
    Enter password: ****
    mysql> start transaction; --开启一个事务
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> update zs_account set money = money - 2000;  --减 2000
    Query OK, 1 row affected (0.07 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> update ls_account set money = money + 2000; -- 加 2000
    Query OK, 1 row affected (0.01 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    

    此时,查询数据:

    数据库中数据还没有变化

    mysql> commit; -- commit 后,数据库数据才会更改
    Query OK, 0 rows affected (0.07 sec)
    

    反应了数据的隔离性,即,commit 之前,事务未结束,此时从数据库查询,数据库也没有变化。

    2.回滚事务

    数据恢复为:

    zs_account money = 5000

    ls_account money = 1000

    mysql> start transaction; --开启一个事务
    Query OK, 0 rows affected (0.00 sec)
    
    mysql> update zs_account set money = money - 2000; --减 2000
    Query OK, 1 row affected (0.04 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    mysql> select * from zs_account;  -- zs 变3000了,只是会话中变了,实际数据库中数据依然未改,还是5000
    +------+-------+
    | name | money |
    +------+-------+
    | 张三 |  3000 |
    +------+-------+
    1 row in set (0.05 sec)
    
    
    mysql> update ls_account set money = money + 2000;  --加 2000
    Query OK, 1 row affected (0.07 sec)
    Rows matched: 1  Changed: 1  Warnings: 0
    
    
    mysql> select * from ls_account; -- ls 变 3000了,但是实际数据库中没变化,事务还未提交
    +------+-------+
    | name | money |
    +------+-------+
    | 李四 |  3000 |
    +------+-------+
    1 row in set (0.00 sec)
    

    然后这个时候断电了

    我去,假如断电了,我现在要回滚

    mysql> rollback; --回滚
    Query OK, 0 rows affected (0.00 sec)
    
    

    此时再在终端查一下:

    mysql> select * from zs_account; --恢复为之前的数据了,当然此时,数据的数据也没有变化
    +------+-------+
    | name | money |
    +------+-------+
    | 张三 |  5000 |
    +------+-------+
    1 row in set (0.00 sec)
    
    mysql> select * from ls_account;
    +------+-------+
    | name | money |
    +------+-------+
    | 李四 |  1000 |
    +------+-------+
    1 row in set (0.00 sec)
    

    再附一张,“蚂蚁小强 ” 大神的图 :

    执行流程图


    四、事务的并发问题

    1.脏读

    • 老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的户口,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高业。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交
    • 实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。
    • 解决办法:Read committed!读提交,能解决脏读问题

    2.不可重复读

    • 程序员拿着工资卡(卡里当然是只有3.6万) ,当他买单时(程序员事务开启) ,收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了。程序员就会很郁闷,明明卡里是有钱的…
    • 一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读
    • 解决办法: Repeatable read

    3.重复读

    • 程序员拿着工资卡(卡里还是有3.6万) ,当他买单时(事务开启,不允许其他事务的 UPDATE修改操作),收费系统事先检测到他的卡里有3.6万,这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。

    4.幻读

    • 程序员某一天去消费,花了2千元,然后他的妻子去查看他今天的消费记录 (,妻子事务开启) ,看到确实是花了2千元,就在这个时候,程序员花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当妻子打印程序员的消费记录清单时(妻子事务提交) ,发现花了1.2万元,似乎出现了幻觉,这就是幻读。

    • 解决办法: Serializable,但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。


    5.对应关系

    附上"蚂蚁"大神的图:

    mysql 默认使用的是 可重复读(repeatable-read)

    另外:

    **查看隔离级别: ** select @@global.tx_isolation,@@tx_isolation;

    设置全局隔离级别: set global transaction isolation level read committed;

    设置当前会话隔离级别: set session transaction isolation level read committed;

    .

  • 相关阅读:
    信息安全系统设计基础第八周期中复习总结
    layui下各种富文本的冲突情况
    TP3.2+find_set_in 以及 find_set_in和like的区别
    tp5+linux+apache php7.1.30环境下,上传图片报错:mkdir():permission denied
    一次基于老古董thinkPHP3.1的修改尝试
    微信网页开发 thinkphp5.0的try-catch和重定向
    CentOS 7.2下服务器配置(linux+apache+php+mysql)
    微信小程序踩坑(不定时更新)
    PHP 定时自动执行代码
    PHP TP5 文章评论+积分+签到
  • 原文地址:https://www.cnblogs.com/friday69/p/9403261.html
Copyright © 2020-2023  润新知