This is a follow up to: php/mysql transaction not rolling back on failure (Codeigniter framework)
I implemented the suggested pattern at the above link. My questions are:
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;
because it can trigger implicit commits. Instead, you should look into using SELECT ... FOR UPDATE
or SELECT ... LOCK IN SHARED MODE
.
If you are using MySQL 5.6, try starting the transaction with
START TRANSACTION READ WRITE;
START TRANSACTION READ ONLY;
I wrote about this in the DBA StackExchange (See row locking within ACID transaction innodb )
If you still wish to use LOCK TABLES;
and UNLOCK TABLES
, keep in mind that LOCK TABLES
starts a new transaction, ROLLBACK
and COMMIT
are still mandatory because UNLOCK TABLES;
triggers an implicit commit. ROLLBACK
gives you the opportunity to throw away changes the transaction was holding. 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.
And I believe it was improved in CodeIgniter v3 (Still in development).
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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.