这是以下内容的后续:php/mysql事务回滚失败(Codeigniter框架)
我在上面的链接中实现了建议的模式。我的问题是:每次查询失败时我需要做回滚吗?似乎我必须检查每个查询的结果,然后做回滚,如果它失败了。这似乎有点重复。
$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');
您应该避免使用LOCK TABLES
和UNLOCK TABLES;
,因为它们会触发隐式提交。相反,您应该考虑使用SELECT ... FOR UPDATE
或SELECT ... LOCK IN SHARED MODE
。
如果你使用的是MySQL 5.6,尝试用
开始事务-
START TRANSACTION READ WRITE;
-
START TRANSACTION READ ONLY;
我在DBA StackExchange中写过这个(参见ACID事务innodb中的行锁定)
如果您仍然希望使用LOCK TABLES;
和UNLOCK TABLES
,请记住LOCK TABLES
启动新事务,ROLLBACK
和COMMIT
仍然是强制性的,因为UNLOCK TABLES;
触发隐式提交。ROLLBACK
使您有机会丢弃事务所持有的更改。UNLOCK TABLES;
将提交您可能想要撤销的更改。
唯一的隐式回滚是终止DB连接
Codeigniter具有内置的事务支持,您不需要手动执行这些操作。
我相信它在CodeIgniter v3(仍在开发中)中得到了改进。
基本上,你所要做的就是这样:
$this->db->trans_start();
$this->db->query('AN SQL QUERY...');
$this->db->query('ANOTHER QUERY...');
$this->db->trans_complete();
调用trans_complete()将在查询失败时自动回滚。
如果你想自己处理错误,你可以这样做:
$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();
}
请记住我指的是CodeIgniter v3,你可以从github上获得它,因为我在一年前放弃了CodeIgniter v2。