翻译者:长风Drupal开发团队(成都长风云信息技术有限公司)
在Drupal开发中,事务的例子如下:
function my_transaction_function() {
// The transaction opens here.
$transaction = $connection->startTransaction();
try {
$id = $connection->insert('example')
->fields([
'field1' => 'mystring',
'field2' => 5,
])
->execute();
my_other_function($id);
return $id;
}
catch (Exception $e) {
$transaction->rollBack();
watchdog_exception('my_type', $e);
}
// $transaction goes out of scope here. Unless it was rolled back, it
// gets automatically commited here.}
function my_other_function($id) {
// The transaction is still open here.
if ($id % 2 == 0) {
$connection->update('example')
->condition('id', $id)
->fields(['field2' => 10])
->execute();
}}
Drupal还支持事务,包括不支持事务的数据库的透明后退。但是,当您尝试同时启动两个事务时,事务会变得相当复杂。在这种情况下,数据库之间的行为也不同。
在C/C++中嵌套锁存在类似的问题。如果代码已经获取锁A并试图获取锁A,则代码将死锁。如果它已经锁定,不尝试获取一遍你写的代码检查,你避免死锁可释放锁过早。
在SQL中,我们也有同样的问题。如果你的代码已经在交易,开始一个新的交易具有令人惊讶的提交当前事务并开始一个新的后果和不幸。
Java通过实现与我们下面测试的嵌套结构的支持来解决嵌套问题。Java允许您将函数标记为“同步”,这使得函数在运行之前等待锁获取,并且在不再需要时释放锁。如果一个同步函数调用同一个类中的另一个函数,则Java跟踪锁定嵌套。外部函数获取锁,内部函数不执行锁定操作,和外部函数返回时释放锁。
虽然我们不能在PHP中声明函数“事务性”,但是我们可以通过使用具有构造函数和析构函数的对象来模拟Java的嵌套逻辑。一个功能简单地称之为“$transaction= $connection-> starttransaction()”作为其第一个(或接近第一)操作使自己的事务。如果一个事务函数调用另一个,我们的交易抽象层巢他们进行没有事务性操作(只要数据库内的嵌套层内见)。
开始一个新的交易,只需调用美元交易= $connection-> starttransaction();在您自己的代码。该交易将只要变量$transaction保持开放,保持在范围内。当美元交易遭到破坏,该事务将被提交。如果你的交易是嵌套在另一个然后Drupal将跟踪每笔交易只做最外层的事务时,最后的交易对象超出了范围,即所有相关的查询成功完成。
您必须指定$connection->startTransaction()返回值;一个变量,在这个例子中。如果你调用方法没有返回值的变量赋值,您的交易将立即使它无用。
回滚一个事务是由连接对象管理($connection-> rollback())在Drupal 8,但通常应通过交易的包装方法($transaction-> rollback())。这应该是通过交易的rollback()方法的原因是因为它回滚事务基于它的名字,其中$connection-> rollback()名称默认为drupal_transaction可能产生意想不到的结果与使用嵌套事务。