PHP事务处理示例


在php中,事务场景我们经常会碰到。这里举一个例子。


正文

在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

https://www.cnblogs.com/minigrasshopper/p/7803938.html

https://www.cnblogs.com/xiezhi/p/5545979.html


返回