事务(Transaction)是会见并大概更新数据库中各类数据项的一个措施执行单位;
事务的ACID特性
事务应该具有4个属性:原子性、一致性、断绝性、一连性
原子性(atomicity)。一个事务是一个不行支解的事情单元,事务中包罗的诸操纵要么都做,要么都不做。
一致性(consistency)。事务必需是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
断绝性(isolation)。一个事务的执行不能被其他事务滋扰。即一个事务内部的操纵及利用的数据对并发的其他事务是断绝的,并发执行的各个事务之间不能相互滋扰。
耐久性(durability)。一连性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操纵或妨碍不该该对其有任何影响。
漫衍式事务:漫衍式事务的参加者、资源打点器、事务打点器等位于不消的节点上,这些差异的节点彼此协作配合完成一个具有逻辑完整性的事务。
mysql从5.0开始支持XA DataSource。Connector/J 版本要利用5.0版本,5.0以下的不支持。
常见的漫衍式事务办理方案
基于XA协议的两阶段提交
XA协议由Tuxedo首先提出的,并交给X/Open组织,作为资源打点器(数据库)与事务打点器的接口尺度。今朝,Oracle、Informix、DB2和Sybase等各大数据库厂家都提供对XA的支持。XA协议回收两阶段提交方法来打点漫衍式事务。XA接口提供资源打点器与事务打点器之间举办通信的尺度接口。XA协议包罗两套函数,以xa_开头的及以ax_开头的。
以下的函数使事务打点器可以对资源打点器举办的操纵:
1)xa_open,xa_close:成立和封锁与资源打点器的毗连。
2)xa_start,xa_end:开始和竣事一个当地事务。
3)xa_prepare,xa_commit,xa_rollback:预提交、提交和回滚一个当地事务。
4)xa_recover:回滚一个已举办预提交的事务。
5)ax_开头的函数使资源打点器可以动态地在事务打点器中举办注册,并可以对XID(TRANSACTION IDS)举办操纵。
6)ax_reg,ax_unreg;答允一个资源打点器在一个TMS(TRANSACTION MANAGER SERVER)中动态注册或除掉注册。
XA实现漫衍式事务的道理如下:
MySQL XA分为两类,内部XA与外部XA;内部XA用于同一实例下跨多个引擎的事务,由各人熟悉的Binlog作为协调者;外部XA用于跨多MySQL实例的分 布式事务,需要应用层参与作为协调者(瓦解时的悬挂事务,全局提交照旧回滚,需要由应用层抉择,对应用层的实现要求较高);
Binlog作为内部XA的协调者,在binlog中呈现的内部xid,在crash recover时,由binlog认真提交。(这是因为,binlog不举办prepare, 只举办commit,因此在binlog中呈现的内部xid,必然可以或许担保其在底层各存储引擎中已经完成prepare)。
MySQL数据库外部XA可以用在漫衍式数据库署理层,实现对MySQL数据库的漫衍式事务支持,譬喻开源的署理东西:网易的DDB,淘宝的TDDL,B2B的Cobar等等。
示例
public function testAction(){ $goods_id=1; $goods_name = "剧本之家"; $num = 1; $rs_order = $this->test->createorder($goods_id,$goods_name,$num); $rs_goods = $this->test->deduction($goods_id,$num); if($rs_order['status'] =="success" && $rs_goods['status']=="success"){ $this->test->commitdb($rs_order['XA']); $this->test->commitdb1($rs_goods['XA']); }else{ $this->test->rollbackdb($rs_order['XA']); $this->test->rollbackdb1($rs_goods['XA']); } print_r($rs_order); echo "<br />"; print_r($rs_goods); die("dddd"); } public function createorder($goods_id,$goods_name,$num){ $XA = uniqid(""); $this->_db->query("XA START '$XA'"); $_rs = true; try { $data = array(); $data['order_id'] = "V".date("YmdHis"); $data['goods_name'] = $goods_name; $data['goods_num'] = $num; $this->_db->insert("temp_orders",$data); $rs = $this->_db->lastInsertId(); if($rs){ $_rs = true; }else{ $_rs = false; } } catch (Exception $e) { $_rs = false; } $this->_db->query("XA END '$XA'"); if($_rs){ $this->_db->query("XA PREPARE '$XA'"); return array("status"=>"success","XA"=>$XA); }else{ return array("status"=>"nosuccess","XA"=>$XA); } } public function deduction($id){ $XA = uniqid(""); $this->db1->query("XA START '$XA'"); $last_rs = true; try { $sql = "select * from temp_goods where id = '$id' and goods_num>0"; $rs = $this->db1->fetchRow($sql); if(!empty($rs)){ $sql = "update temp_goods set goods_num = goods_num-1 where id = '$id'"; $rd = $this->db1->query($sql); if($rd){ $last_rs = true; }else{ $last_rs = false; } }else{ $last_rs = false;; } } catch (Exception $e) { $last_rs = false;; } $this->db1->query("XA END '$XA'"); if($last_rs){ $this->db1->query("XA PREPARE '$XA'"); return array("status"=>"success","XA"=>$XA); }else{ return array("status"=>"nosuccess","XA"=>$XA); } } //提交事务! public function commitdb($xa){ return $this->_db->query("XA COMMIT '$xa'"); } //回滚事务 public function rollbackdb($xa){ return $this->_db->query("XA ROLLBACK '$xa'"); } //提交事务! public function commitdb1($xa){ return $this->db1->query("XA COMMIT '$xa'"); } //回滚事务 public function rollbackdb1($xa){ return $this->db1->query("XA ROLLBACK '$xa'"); }
总结