简体   繁体   English

使用锁定表时的事务+回滚

[英]transaction + rollback when using lock tables

This is a follow up to: php/mysql transaction not rolling back on failure (Codeigniter framework) 这是后续措施: 失败时php / mysql事务不回滚(Codeigniter框架)

I implemented the suggested pattern at the above link. 我在上面的链接中实现了建议的模式。 My questions are: 我的问题是:

  1. Do I need to do rollback every time a query fails? 每次查询失败我都需要回滚吗? It seems I have to check each query for its result and then do a rollback if it fails. 看来我必须检查每个查询的结果,然后在失败时进行回滚。 This seems kind of repetitive . 这似乎是重复的。

     $this->db->query("SET autocommit=0"); //Lock tables invovled in sale transaction so we don't have deadlock $this->db->query('LOCK TABLES '.$this->db->dbprefix('customers').' WRITE, '.$this->db->dbprefix('sales').' WRITE, '.$this->db->dbprefix('store_accounts').' WRITE, '.$this->db->dbprefix('sales_payments').' WRITE, '.$this->db->dbprefix('sales_items').' WRITE, '.$this->db->dbprefix('giftcards').' WRITE, '.$this->db->dbprefix('location_items').' WRITE, '.$this->db->dbprefix('inventory').' WRITE, '.$this->db->dbprefix('sales_items_taxes').' WRITE, '.$this->db->dbprefix('sales_item_kits').' WRITE, '.$this->db->dbprefix('sales_item_kits_taxes').' WRITE,'.$this->db->dbprefix('people').' READ,'.$this->db->dbprefix('items').' READ ,'.$this->db->dbprefix('employees_locations').' READ,'.$this->db->dbprefix('locations').' READ, '.$this->db->dbprefix('items_tier_prices').' READ , '.$this->db->dbprefix('location_items_tier_prices').' READ, '.$this->db->dbprefix('items_taxes').' READ, '.$this->db->dbprefix('item_kits').' READ , '.$this->db->dbprefix('location_item_kits').' READ, '.$this->db->dbprefix('item_kit_items').' READ, '.$this->db->dbprefix('employees').' READ , '.$this->db->dbprefix('item_kits_tier_prices').' READ , '.$this->db->dbprefix('location_item_kits_tier_prices').' READ, '.$this->db->dbprefix('location_items_taxes').' READ , '.$this->db->dbprefix('location_item_kits_taxes'). ' READ, '.$this->db->dbprefix('item_kits_taxes'). ' READ'); if (!$this->db->insert('sales',$sales_data)) { $this->db->query("ROLLBACK"); $this->db->query('UNLOCK TABLES'); return -1; } 

... ... ……

$this->db->query("COMMIT");         
$this->db->query('UNLOCK TABLES');  

You should get away from using LOCK TABLES and UNLOCK TABLES; 您应该避免使用LOCK TABLESUNLOCK TABLES; because it can trigger implicit commits. 因为它可以触发隐式提交。 Instead, you should look into using SELECT ... FOR UPDATE or SELECT ... LOCK IN SHARED MODE . 相反,您应该研究使用SELECT ... FOR UPDATESELECT ... LOCK IN SHARED MODE

If you are using MySQL 5.6, try starting the transaction with 如果您使用的是MySQL 5.6,请尝试使用

  • START TRANSACTION READ WRITE;
  • START TRANSACTION READ ONLY;

I wrote about this in the DBA StackExchange (See row locking within ACID transaction innodb ) 我在DBA StackExchange中写过有关此内容的信息(请参见ACID事务innodb中的行锁定

If you still wish to use LOCK TABLES; 如果您仍然希望使用LOCK TABLES; and UNLOCK TABLES , keep in mind that LOCK TABLES starts a new transaction, ROLLBACK and COMMIT are still mandatory because UNLOCK TABLES; UNLOCK TABLES ,请记住, LOCK TABLES开始一个新的事务,因为UNLOCK TABLES;ROLLBACKCOMMIT仍然是必需的UNLOCK TABLES; triggers an implicit commit. 触发隐式提交。 ROLLBACK gives you the opportunity to throw away changes the transaction was holding. ROLLBACK使您有机会放弃交易持有的更改。 UNLOCK TABLES; will commit changes you probably wanted to undo. 将提交您可能要撤消的更改。

The only implicit rollback is the termination of a DB Connection. 唯一的隐式回滚是终止数据库连接。

Codeigniter has built-in transactions support, You don't need to do these manually. Codeigniter具有内置的事务支持,您无需手动进行。

And I believe it was improved in CodeIgniter v3 (Still in development). 而且我相信它在CodeIgniter v3(仍在开发中)中得到了改进。

Basically, All you have to do is something like this: 基本上,您要做的就是这样:

$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->trans_complete();

Calling trans_complete() will automatically roll-back when there's a failed query. 查询失败时,调用trans_complete()将自动回滚。

If you want to handle errors yourself, You'll do something like this: 如果您想自己处理错误,则可以执行以下操作:

$this->db->trans_begin();

$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');

if ($this->db->trans_status() === FALSE)
{
        $this->db->trans_rollback();
}
else
{
        $this->db->trans_commit();
}

Please keep in mind I am referring to CodeIgniter v3 which you can get it off github as I ditched the CodeIgniter v2 over a year ago. 请记住,我指的是CodeIgniter v3,因为一年多前我放弃了CodeIgniter v2,可以将其从github上删除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM