事务处理
事务是确保数据库一致的机制,是企业级数据库的一个重要组成部分,很多业务过程都包括多个步骤。如果任何一个步骤失败,则所有步骤都不应该发生。例如,在一组有序的数据库操作中,如果组中的所有SQL语句都操作成功,则认为事务成功,事务被提交,其修改将作用于所有其他数据库进程;如果在事务组中只有一个环节操作失败,事务不成功,则整个事务将被回滚,该事务中的所有操作都将被取消。事务处理能够有效解决数据库操作的不同步问题,同时提升大批量数据操作的执行效率。
在MySQL4.0及其以上版本中均默认支持事务,但MySQL目前只有InnoDB和BDB两种数据表类型才支持事务,两个表类型具有相同的特性,InnoDB表类型具有比BDB类型还丰富的特性,速度更快,因此建议使用InnoDB表类型。
默认情况下,MySQL是以自动提交模式运行的,这就意味着所执行的每一个语句都将立即写入数据库中。但如果使用事务安全的表格类型,是不希望有自动提交的行为。mysqli扩展模块中目前没有提供与SQL命令START TRANSACTION相对应的方法,如果想使用事务,必须执行mysqli对象中的autocommit(0)方法关闭MySQL事务机制的自动提交模式。关闭提交模式之后,后续执行的SQL命令将构成一个事务,直到调用mysqli类对象的commit()方法提交它们或者rollback()方法撤销它们为止。
综上所述,mysqli操作MySQL事务需要两步:
- 修改数据库表的类型为InnoDB或BDB
- 关闭自动提交功能
代码实例
mysqli操作MySQL事务
<?php
$host = 'localhost'; //指定MySQL服务器
$username = 'root'; //指定用户名
$password = 'root'; //指定登录密码
$dbname = 'db_book_php_15'; //指定数据库名称
//mysqli对象化
$mysqli = new mysqli($host,$username,$password,$dbname); //连接数据库
/* 检查连接,如果连接出错输出错误信息并退出程序 */
if (mysqli_connect_errno ()) {
printf ( "连接失败:<br>", mysqli_connect_error () );
exit ();
}
$success=TRUE; //设置事务执行状态
$price=8000; //转账的数目
$mysqli->autocommit(0); //暂时关闭MySQL事务机制的自动提交模式
//执行从userA记录中减少cash的值,返回1表示成功,否则执行失败
$result=$mysqli->query("UPDATE tb_account SET cash=cash-$price WHERE name='userA'");
//如果SQL语句执行失败或没有改变记录中的值,将$sucess的值设置为FALSE
if(!$result or $mysqli->affected_rows !=1) {
$success=FALSE; //设置$sucess的值为FALSE,任何一个sql语句出现错误,都会影响$success变为FALSE
}
//执行向userB记录中添加cash的值,返回1表示成功,否则执行失败
$result=$mysqli->query("UPDATE tb_account SET cash=cash+$price WHERE name='userB'");
//如果SQL语句执行失败或没有改变记录中的值,将$sucess的值设置为FALSE
if(!$result or $mysqli->affected_rows !=1) {
$success=FALSE; //设置$sucess的值为FALSE,任何一个sql语句出现错误,都会影响$success变为FALSE
}
if($success){ //如果$success的值为TRUE
$mysqli->commit(); //事务提交给数据库
echo "转账成功!"; //输出成功的提示信息
}else{ //如果$success的值为FLASE,事务中有错误
$mysqli->rollback(); //回滚当前的事务,所有SQL命令都被撤销
echo "转账失败!"; //输出不成功的提示信息
}
$mysqli->autocommit(1); //开启MySQL事务机制的自动提交模式
$mysqli->close(); //关闭与MySQL数据库的连接
?>
PDO使用事务处理
在PHP中使用事务包括以下几个步骤:
- 1、关闭自动提交
$db = new PDO($dsn, $user, $pass);
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false); //关闭 PDO的自动提交
- 2、开启事务处理
$db->beginTransaction();
- 3、全部SQL语句正确完成,则提交事务;如果有一个错误则回滚(一般事务处理运行在try/catch语句中)
try{
$db->beginTransaction();
//SQL语句...
//SQL语句...
$db->commit();
}catch(PDOException $e){
$db->rollBack();
}
- 4、开启自动提交
调用commit()方法之后自动恢复自动提交模式
<?php
$dbms='mysql'; //数据库类型
$host='localhost'; //数据库主机名
$dbName='db_book_php_16'; //使用的数据库
$user='root'; //数据库连接用户名
$pass='root'; //密码
$dsn="$dbms:host=$host;dbname=$dbName";
try {
//初始化PDO对象,创建数据库连接
$db = new PDO($dsn, $user, $pass);
$db->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION); //设置为异常模式
$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false); //关闭 PDO的自动提交
$db->beginTransaction(); //开启事务处理
$stmt=$db->prepare("insert into tb_test(name) values(?)"); //PDO预处理
$data=array( //定义批量插入的数据
array("张三"),
array("李四"),
array("王五")
);
foreach($data as $v){ //使用foreach语句逐一把数组中的数据插入到数据库
$stmt->execute($v);
echo $db->lastInsertId()."<br>"; //显示插入记录的id编号
}
$db->commit(); //提交事务
echo "提交成功!";
}catch (PDOException $e) {
$db->rollBack(); //事务回滚
die("提交失败!");
}