正文
在php中,事务场景我们经常会碰到。事务是对数据库数据保存处理而言的,要么都处理成功,要么一条都不应该保存。
事务支持四大特性(ACID):原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)以及持久性(Durability)。 通俗地讲,在一个事务中执行的任何操作,即使是分阶段执行的,也能保证安全地应用于数据库,并在提交时不会受到来自其他连接的干扰。 事务操作也可以根据请求自动撤销(假设还没有提交),这使得在脚本中处理错误更加容易。
我们一般把事务放在PHP异常处理结构中:
try
{
...
throw new Exception("Always throw this error");
} catch (Exception $e) {
echo 'Message: ' .$e->getMessage();
}
PDO实现
try {
$dbh = new PDO('odbc:SAMPLE', 'db2inst1', 'ibmdb2', array(PDO::ATTR_PERSISTENT => true));
echo "Connected\n";
} catch (Exception $e) {
die("Unable to connect: " . $e->getMessage());
}
try {
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$dbh->beginTransaction();
$dbh->exec("insert into staff (id, first, last) values (23, 'Joe', 'Bloggs')");
$dbh->exec("insert into salarychange (id, amount, changedate) values (23, 50000, NOW())");
$dbh->commit();
} catch (Exception $e) {
$dbh->rollBack();
echo "Failed: " . $e->getMessage();
}
mysqli实现
MySQL中只有Innodb和BDb类型数据库引擎的数据表才能支持事务处理!其他的类型是暂不支持事务的!
$mysqli = new mysqli('localhost','root','mayi1991','mysqldemo');
if($mysqli->connect_error){
die('数据库连接错误'.$mysqli->connect_error);
}
//关闭数据库自动提交
$mysqli->autocommit(false);
$sql1 = "update account set balance = balance - 2 where id = 1";
//这里故意写错属性balance1
$sql2 = "update account set balance1 = balance + 2 where id = 2";
$result1 = $mysqli->query($sql1);
$result2 = $mysqli->query($sql2);
if (!$result1 || !$result2) {
die('操作错误'.$mysqli->error);
$mysqli->rollback(); // 事务回退
} else {
// 操作全部正确后再提交
$mysqli->commit();
}
$mysqli->close();
mysql实现
$conn = mysql_connect('localhost','root','root') or die ("数据连接错误!!!");
mysql_select_db('test',$conn);
mysql_query("set names 'GBK'"); //使用GBK中文编码;
//开始一个事务
mysql_query("BEGIN"); //或者mysql_query("START TRANSACTION");
$sql = "INSERT INTO `user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')";
$sql2 = "INSERT INTO `user` (`did`, `username`, `sex`) VALUES (NULL, 'test1', '0')";//这条我故意写错
$res = mysql_query($sql);
$res1 = mysql_query($sql2);
if ($res && $res1) {
mysql_query("COMMIT");
echo '提交成功。';
} else {
mysql_query("ROLLBACK");
echo '数据回滚。';
}
mysql_query("END");
Yii2实现
下面举一个yii2中使用的标准的示例:
$connection = Yii::$app->db;
$transaction = $connection->beginTransaction();
try {
// 一些处理
if ( false ) {
throw new \Exception('异常');
}
$transaction->commit();
return ['error' => 0, 'data' => []];
} catch ( \Exception $e ) {
$transaction->rollBack();
return ['error' => $e->getMessage(), 'data' => []];
}
参考资料
PHP 异常处理 http://www.w3school.com.cn/php/php_exception.asp
PHP 手册 函数参考 数据库扩展 数据库抽象层 PDO 事务与自动提交 https://www.php.net/manual/zh/pdo.transactions.php