关于事务的问题我们就不多解释了,等以后学习MySQL的时候再详细了解。今天我们主要对PDO中的操作事务做一些小测试,可能会发现一些有趣的内容。在MyISAM上使用事务怎么样?首先,相信学过一点MySQL相关知识的人都知道,MySQL常用的两种表类型是InnoDB和MyISAM。当然,我们今天不会把它们的所有区别都说一遍,但是有一个区别是最明显的,那就是MyISAM不支持事务。那么,如果我们在PDO操作中对MyISAM进行事务操作呢?//myisamtry{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$pdo->beginTransaction();$pdo->exec("insertintotran_myisam(name,age)values('Joe',12)");$pdo->exec("insertintotran_myisam2(name,age)values('Joe',12,33)");//睡眠(30);$pdo->commit();}catch(Exception$e){$pdo->rollBack();回声“失败:”。$e->getMessage(),PHP_EOL;}tran_myisam和tran_myisam2表都是MyISAM表。在这段代码中,我们故意错了tran_myisam2的insert语句,让它去抓。实际执行的结果是错误信息正常输出,同时插入了tran_myisam表中的数据。换句话说,对MyISAM表的事务操作没有影响。当然PDO是不会主动报错的。如果我们把第二条SQL语句也做成普通语句,PDO只会正常结束,没有任何错误和提示信息。//innodbtry{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$pdo->beginTransaction();$pdo->exec("insertintotran_innodb(name,age)values('Joe',12)");$pdo->exec("insertintotran_innodb2(name,age)values('Joe',12,3)");//睡眠(30);$pdo->commit();}catch(Exception$e){$pdo->rollBack();回声“失败:”。$e->getMessage(),PHP_EOL;}我们可以开启sleep(30);注释这行代码,即在事务提交中暂停30秒,然后查看MySQL中的infomation_schema.INNODB_TRX表。此表显示正在执行的事务。在执行InnoDB类型的表时可以看到一条正在执行的事务的记录,但是在MyISAM类型的表中是看不到任何信息的。如果事务未提交或回滚会怎样?假设我们忘了写commit(),没有报错,这条语句会执行成功吗?就像下面的代码。尝试{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$pdo->beginTransaction();$pdo->exec("insertintotran_innodb(name,age)values('Joe',12)");$pdo->exec("insertintotran_innodb2(name,age)values('Joe',12)");//忘记写$pdo->commit();}catch(Exception$e){$pdo->rollBack();回声“失败:”。$e->getMessage(),PHP_EOL;}PHP会在脚本执行结束后回滚这个事务,实际上是在$pdo对象被销毁的时候。也就是说这里的SQL语句是不会执行的。不过,尽量不要这样做,因为在正式环境下,我们的代码是非常复杂的,不一定能成功析构。这种情况下,可能会有事务被长期占用,最后的结果会是MySQL的IPQS极高,很难找到原因。所以,在使用事务的时候,一定要记住commit()和rollBack()是我们的兄弟,不能丢下他们。如果上一个事务没有提交或者回滚,下一个事务会被执行吗?同样,我们在上一个问题的基础上继续延伸。如果两个事务依次执行,第一个事务没有提交或者回滚,下一个事务还能执行吗?//innodbtry{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$pdo->beginTransaction();$pdo->exec("insertintotran_innodb(name,age)values('Joe',12)");$pdo->exec("insertintotran_innodb2(name,age)values('Joe',12)");//忘记写$pdo->commit();}catch(Exception$e){$pdo->rollBack();回声“失败:”。$e->getMessage(),PHP_EOL;}//innodbtry{$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);$pdo->beginTransaction();$pdo->exec("insertintotran_innodb(name,age)values('BW',12)");$pdo->exec("insertintotran_innodb2(name,age)values('BW',12)");//睡眠(30);$pdo->commit();}catch(Exception$e){$pdo->rollBack();回声“失败:”。$e->getMessage(),PHP_EOL;//Failed:Thereisalreadyanactivetransaction}我们可以看到第二个事务直接报错了,内容是:“这里已经有一个活跃的事务”。也就是说,如果前一个事务没有提交或者回滚,那么第二个事务就无法执行。总结今天我们只研究和测试了几个与交易相关的小问题,但是小问题可能会造成严重的线上事故,所以大家在开发的时候一定要小心。以后深入学习MySQL的时候再研究事务的细节。测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202008/source/在PHP中使用PDO操作事务的一些小测试。PHP参考文档:https://www.php。net/manual/zh/pdo.transactions.php各媒体平台均可搜索【硬核项目经理】
