您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

php操作mysql事务深度测试

2024/6/28 9:25:11发布17次查看
一 事务是什么? 正常的sql语句是一条一条的执行,各个sql之间互不影响。 事务的机制类于一个黑盒,黑盒里的sql语句(多条)要么全部成功了,要么全部失败了。(土话就这么讲,术语我就不说了) 二 如何应用事务? 一个事务有三个关键步骤:开始、提交、回滚
一 事务是什么?
正常的sql语句是一条一条的执行,各个sql之间互不影响。
事务的机制类似于一个黑盒,黑盒里的sql语句(多条)要么全部成功了,要么全部失败了。(土话就这么讲,术语我就不说了) 
二 如何应用事务?
一个事务有三个关键步骤:开始、提交、回滚。
开始就是要告诉数据库我要开始事务了,那么数据库就会给你提供一个黑盒,接下来你就开始执行sql,如果sql都没问题,那么就执行提交,那么黑盒里操作的结果就会真正写入数据库,如果有失败的,那么执行以下回滚,数据库没有任何改变。
从这个角度看,黑盒更像是一个“沙盒”。
php想对应的是操作mysqli库的三个方法:mysqli::autocommit,mysqli::commit(),mysqli::rollback().
三 单元测试
1.创建mysql测试表(myisam引擎不支持事务,innodb引擎可以支持,所以将测试表建为innodb引擎)
表名:transaction_test,两个字段:id主键自增,content字符串类型。
create table `transaction_test`( `id` int(11) not null auto_increment, `content` varchar(256) default null, primary key (`id`)) engine=innodb default charset=utf8 comment='php事务测试表';
2.插入初始化数据
insert into transaction_test(content) values('北京'),('上海'),('广州');
如图:
3.php连接数据库并插入数据测试
创建transaction_test.php
php$mysqli = new mysqli(localhost, root, , test);/* check connection */if (mysqli_connect_errno()) { printf(connect failed: %s\n, mysqli_connect_error()); exit();}/* set charset */$sql_set_charset = set names utf8;$query = $mysqli->query($sql_set_charset);if($query===false) { echo 'set charset failed
'; exit(0);}/* insert */$sql_1 = insert into transaction_test(`content`) values('天津');$query1 = $mysqli->query($sql_1);if($query1===false) { echo 'query1 failed
';} else { printf(insert_id one: %d
, $mysqli->insert_id);}$mysqli->close();?>
运行效果及数据库结果:
插入ok。
4.测试mysqli::autocommit()。
autocommit()方法是设置数据库是否自动提交,参数为true和false,默认true。默认状态下每执行一次query(),数据库就会提交一次,那么如果设置为false,数据库就不会自动提交,那么就可以开始事务了,具体用法看下面的测试:
在上面代码的基础上,在插入数据的sql语句query之前,关闭自动提交。
php$mysqli = new mysqli(localhost, root, , test);/* check connection */if (mysqli_connect_errno()) { printf(connect failed: %s\n, mysqli_connect_error()); exit();}/* set charset */$sql_set_charset = set names utf8;$query = $mysqli->query($sql_set_charset);if($query===false) { echo 'set charset failed
'; exit(0);}/* 关闭自动提交,开始事务 */$mysqli->autocommit(false);/* insert */$sql_1 = insert into transaction_test(`content`) values('重庆');$query1 = $mysqli->query($sql_1);if($query1===false) { echo 'query1 failed
';} else { printf(insert_id one: %d
, $mysqli->insert_id);}$mysqli->close();?>
运行效果及数据库结果:
分析:php返回id为5,但数据库却没有这条记录,说明开始事务之后所执行的query只是在一个“沙盒”里,并没有真正的写入到数据库。
5.测试mysqli::commit()
在上面代码中插入代码的后面加上commit()方法。
php$mysqli = new mysqli(localhost, root, , test);/* check connection */if (mysqli_connect_errno()) { printf(connect failed: %s\n, mysqli_connect_error()); exit();}/* set charset */$sql_set_charset = set names utf8;$query = $mysqli->query($sql_set_charset);if($query===false) { echo 'set charset failed
'; exit(0);}/* 关闭自动提交,开始事务 */$mysqli->autocommit(false);/* insert */$sql_1 = insert into transaction_test(`content`) values('哈尔滨');$query1 = $mysqli->query($sql_1);if($query1===false) { echo 'query1 failed
';} else { printf(insert_id one: %d
, $mysqli->insert_id);}/* 事务提交 */$mysqli->commit();$mysqli->close();?>
运行效果及数据库结果:
分析:执行提交后数据就真正写入数据库了,另外通过id是6可以看出,刚才没有提交的事务虽然没有写入数据库,但是却消耗了一个自增的id。
6.测试mysqli::rollback()
将上面的commit()换成rollback()
php$mysqli = new mysqli(localhost, root, , test);/* check connection */if (mysqli_connect_errno()) { printf(connect failed: %s\n, mysqli_connect_error()); exit();}/* set charset */$sql_set_charset = set names utf8;$query = $mysqli->query($sql_set_charset);if($query===false) { echo 'set charset failed
'; exit(0);}/* 关闭自动提交,开始事务 */$mysqli->autocommit(false);/* insert */$sql_1 = insert into transaction_test(`content`) values('沈阳');$query1 = $mysqli->query($sql_1);if($query1===false) { echo 'query1 failed
';} else { printf(insert_id one: %d
, $mysqli->insert_id);}/* 事务回滚 */$mysqli->rollback();$mysqli->close();?>
运行效果及数据库结果:
分析:同样是返回的id是7,但数据库没有插入这条记录。那这跟上面的不写rollback()的结果不是一样吗?肯定不一样,继续测试。
7.继续测试rollback()
把上面代码的rollback()去掉,在上面的insert语句的query之后,修改autocommit为true,因为一个事务完成之后还要执行其他的sql语句,要把自动提交恢复到默认状态,然后再执行一次insert语句。
php$mysqli = new mysqli(localhost, root, , test);/* check connection */if (mysqli_connect_errno()) { printf(connect failed: %s\n, mysqli_connect_error()); exit();}/* set charset */$sql_set_charset = set names utf8;$query = $mysqli->query($sql_set_charset);if($query===false) { echo 'set charset failed
'; exit(0);}/* 关闭自动提交,开始事务 */$mysqli->autocommit(false);/* insert */$sql_1 = insert into transaction_test(`content`) values('沈阳');$query1 = $mysqli->query($sql_1);if($query1===false) { echo 'query1 failed
';} else { printf(insert_id one: %d
, $mysqli->insert_id);}/* 事务回滚 $mysqli->rollback(); *//* 恢复自动提交 */$mysqli->autocommit(true);/* insert */$sql_2 = insert into transaction_test(`content`) values('长春');$query2 = $mysqli->query($sql_2);if($query2===false) { echo 'query2 failed
';} else { printf(insert_id two: %d
, $mysqli->insert_id);}$mysqli->close();?>
运行效果及数据库结果:
分析:虽然前面开启了事务,但是自动提交恢复默认之后,第一条insert语句同样写进了数据库,所以不写rollback()并没有回滚。
8 继续测试rollback()
将上面代码中的rollback()的注释去掉
php$mysqli = new mysqli(localhost, root, , test);/* check connection */if (mysqli_connect_errno()) { printf(connect failed: %s\n, mysqli_connect_error()); exit();}/* set charset */$sql_set_charset = set names utf8;$query = $mysqli->query($sql_set_charset);if($query===false) { echo 'set charset failed
'; exit(0);}/* 关闭自动提交,开始事务 */$mysqli->autocommit(false);/* insert */$sql_1 = insert into transaction_test(`content`) values('沈阳');$query1 = $mysqli->query($sql_1);if($query1===false) { echo 'query1 failed
';} else { printf(insert_id one: %d
, $mysqli->insert_id);}/* 事务回滚 */$mysqli->rollback();/* 恢复自动提交 */$mysqli->autocommit(true);/* insert */$sql_2 = insert into transaction_test(`content`) values('长春');$query2 = $mysqli->query($sql_2);if($query2===false) { echo 'query2 failed
';} else { printf(insert_id two: %d
, $mysqli->insert_id);}$mysqli->close();?>
运行效果及数据库结果:
分析:id为10的记录没有插入到数据库,这次执行回滚了。
--------------------------------------------------------------------------------------------------------------
9 基于以上的测试,应该对autocommit(),commit(),rollback()有一个比较深的认识了,最后贴一段代码模拟一下真实环境
1 php 2 $mysqli = new mysqli(localhost, root, , test); 3 4 /* check connection */ 5 if (mysqli_connect_errno()) { 6 printf(connect failed: %s\n, mysqli_connect_error()); 7 exit(); 8 } 9 10 /* set charset */11 $sql_set_charset = set names utf8;12 $query = $mysqli->query($sql_set_charset);13 if($query===false) {14 echo 'set charset failed
';15 exit(0);16 }17 18 /* 关闭自动提交,开始事务 */19 $mysqli->autocommit(false);20 21 /* insert */22 $commit = true;23 $sql_array = array(insert into transaction_test(`content`) values('石家庄'),insert into transaction_test(`content2`) values('郑州'));24 foreach($sql_array as $key=>$item) {25 $query = $mysqli->query($item);26 if($query===false) {27 /* 事务回滚 */28 printf(query failed : %d
, $key);29 $mysqli->rollback();30 $commit = false;31 break;32 } else {33 printf(insert_id $key: %d
, $mysqli->insert_id);34 }35 }36 37 /* 提交事务 */38 if($commit) {39 $mysqli->commit();40 }41 42 /* 恢复自动提交 */43 $mysqli->autocommit(true);44 45 /* insert */46 $sql_2 = insert into transaction_test(`content`) values('最后插入');47 $query2 = $mysqli->query($sql_2);48 if($query2===false) {49 echo 'query2 failed
';50 } else {51 printf(insert_id two: %d
, $mysqli->insert_id);52 }53 54 $mysqli->close();55 ?>
分析:上面的代码中23行的两条sql语句都是正确的,测试的时候可以这样测:两条都正确,1正确2不正确,1不正确2正确,1和2都不正确。
结果:(只有两条都正确的时候才会真正写入数据库,其他3种情况都回滚了)
更广阔的的天地就靠大家发挥了。
貌似这里php的人少,.net人要多一点,希望写的有用。
作者:老默http://www.cnblogs.com/laomo/
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product