MySQL事务回滚

134 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第九天,点击查看活动详情 最近学习MySQL学到了事务回滚,对其定义及利用有了一定的学习。

应用场景

事物回滚应用的场景还是比较多的,举个简单的例子: 我们银行ATM机进行取钱

  1. 输入密码,登录自己的账户
  2. 连接到后台数据库
  3. 获取账户余额
  4. 输入转账金额
  5. 后台数据库对金额进行减去操作
  6. ATM吐出钱

这些步骤缺一不可,假如说在第五步中后台已经减去了金额但是ATM确没有吐出钱,那么这个取钱行为就不成立 这个时候就需要数据库的 事务回滚 ,即在整个过程中任意步骤出错整个事务就回滚回去

具体代码实现

下面代码简单模仿转账场景:

<?php
    //sql基本操作
    /*
    * create table `pay`(
    *     id int(10) not null,
    *     name varchar(20) not null.
    *     money float(5) not null
    * );
    *    insert pay (id,`name`,`money`) values(01,"alice","100");
        insert pay (id,`name`,`money`) values(02,"bob","150");
        insert pay (id,`name`,`money`) values(03,"coco","50");
    */
    //连接数据库
    $link = new Mysqli("localhost","root","zhuangyan","test");
    if ($link->connect_error) {
        exit($link->connect_error());
    }else{
            print "连接成功";
        }
    if(isset($_POST["submit"])){
        //关闭自动提交
        $link->autocommit(FALSE);
        try{
            $money = null;
            //查询用户余额
            $sqls = "select money from `pay` where name = '{$_POST["name"]}'";
            $res = $link->query($sqls);
            $money = $res->fetch_assoc()["money"];
            //更新余额
            $sqlt = "update `pay` set `money` =" . ($money-$_POST["money"]) ." where name = '{$_POST["name"]}'";
            print ("您的余额为:".$money-$_POST["money"]);
            $link->query($sqlt);
            if($_POST["money"] > $money) {
                throw new Exception ("取钱失败");
            }else{
                print "取钱成功";
            }
            //开启提交事务
            $link->commit();
        }catch(Exception $e){
            print $e->getMessage();
            $link->rollback();
        }
        //开启自动提交数据库更改
        $link->autocommit(true);
    }
    $link->close();


?>
<!DOCTYPE html>
<html>
<head>
    <title>Pay</title>
</head>
<body>
    <form method="POST">
        <input type="text" name="name">
        <input type="number" name="money">
        <input type="submit" name="submit" value="取钱">
    </form>
</body>
</html>

在MySQL里面只有innodb支持事务回滚,这边可以自行搜索下MySQL的数据库引擎 因此需要在phpstudy中设置数据库引擎为innodb,之后重启mysql

如果上面这个方法不成功的话可以在建表的时候指定为innodb,如:

create table `pay`(
         id int(10) not null,
         name varchar(20) not null,
         money float(5) not null
)type=innodb;

我这里是建表后意识到这个问题的,所以使用alter进行更新

alter table pay engine=InnoDB;

演示效果

表pay的最初状态

image.png

alice转账50元

image.png

alice继续转账100

image.png