事务功能是企业级数据库的一个重要部分,因为很多业务过程都包括多个步骤,并不是简单的操作一个数据表就能完成的。比如要在人员管理系统中删除一个人员,既要删除人员的基本资料,还要删除所有与该员工有关的信息,如邮件、文章等等,这一系列的数据库操作就构成了一个事务。
注意:在 MySQL 数据库中,只有使用了 Innodb 数据库引擎的数据库或表才支持事务,更多详细的介绍可以查看《MySQL事务》。
PHP 中想要使用事务有两种方式,一是使用 mysqli_begin_transaction()、mysqli_commit()、mysqli_rollback() 等函数来启动、提交或回滚一个事务;再者就是使用 mysqli_autocommit() 函数来关闭 MySQL 事务的自动提交模式。下面我们先来介绍以下这几个函数。
1) begin_transaction()
mysqli_begin_transaction() 函数可以启动一个事务,其语法格式如下:
面向对象风格的写法:
mysqli::begin_transaction([int $flags = 0[, string $name]])
面向过程风格的写法:
mysqli_begin_transaction(mysqli $link[, int $flags = 0[, string $name]])
参数说明如下:
- $link:面向过程风格的写法中,表示由 mysql_connect() 函数创建的数据库连接;
-
$flags:可选参数,可以是以下所示的值:
- MYSQLI_TRANS_START_READ_ONLY:以只读模式启动事务,需要 MySQL5.6 及以上的版本;
- MYSQLI_TRANS_START_READ_WRITE:以读写模式启动事务,需要 MySQL5.6 及以上的版本;
- MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT:使用一致快照模式启动事务。
- $name:可选参数,用来设置事务的保存点名称。
2) mysqli_commit()
mysqli_commit() 函数可以提交一个事务,其语法格式如下:
面向对象风格的写法:
mysqli::commit()
面向过程风格的写法:
mysqli_commit(mysqli $link)
其中 $link 为使用 mysqli_connect() 函数创建的数据库连接。
3) mysqli_rollback()
mysqli_rollback() 函数可以回退当前事务,其语法格式如下:
面向对象风格的写法:
mysqli::rollback()
面向过程风格的写法:
mysqli_rollback(mysqli $link)
其中 $link 为使用 mysqli_connect() 函数创建的数据库连接。
4) mysqli_autocommit()
mysqli_autocommit() 函数可以打开或关闭本次数据库连接的自动提交事务模式,其语法格式如下:
面向对象风格的写法:
mysqli::autocommit(bool $mode)
面向过程风格的写法:
mysqli_autocommit(mysqli $link, bool $mode)
其中 $link 为使用 mysqli_connect() 函数创建的数据库连接,$mode 用来设置是否打开自动提交模式。
了解了这几个函数的语法后,下面通过示例程序来演示事务的使用。
【示例】假设有 userA 和 userB 两个账户,然后使用 userA 账户向 userB 账号中转账,使用事务来保证 userA 账户中减去一定金额的同时,userB 账户中得到相等的金额。首先需要在数据库中创建一个 InnoDB 类型的数据表 accoubnt,并创建上面的两个账户的信息,如下所示:
DROP TABLE IF EXISTS `account`; CREATE TABLE `account` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '用户ID', `name` varchar(45) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '用户名', `cash` decimal(9, 2) NOT NULL COMMENT '账户余额', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic; INSERT INTO `account` VALUES (1, 'userA', 100000.00); INSERT INTO `account` VALUES (2, 'userB', 90000.00);
使用 mysqli_begin_transaction()、mysqli_commit()、mysqli_rollback() 等函数的实现代码如下所示:
<?php $link = new mysqli('127.0.0.1', 'root', 'root', 'testdb'); // 连接数据库 if(mysqli_connect_errno()){ // 检查连接错误 printf("连接失败:%s<br>", mysqli_connect_error()); exit(); } $link -> begin_transaction(); // 开始事务 $success = true; // 设置事务状态 $price = 999; // 转账金额 $sql1 = "UPDATE account SET cash=cash-$price WHERE name='userA'"; // 从 userA 账户转出的 SQL 语句 $result = $link -> query($sql1); // 执行SQL语句 if(!$result || $link->affected_rows != 1){ // 如果执行失败则修改事务状态 $success = false; } $sql2 = "UPDATE account SET cash=cash+$price WHERE name='userB'"; // 向 userB 账户中转入的 SQL 语句 $res = $link -> query($sql2); // 执行SQL语句 if(!$res || $link->affected_rows != 1){ // 如果执行失败则修改事务状态 $success = false; } if($success){ // 根据事务状态选择提交或者回滚事务 $link->commit(); echo '转账成功!'; }else{ $link->rollback(); echo '转账失败!'; } $link->close(); ?>
使用 mysqli_autocommit() 函数实现的话与上面的代码基本相同,只需要将上面代码的第七行更改为下面的样子即可:
$link -> autocommit(0);
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/tech/pnotes/24022.html