PHP與MYSQL事務處理 PHP與MYSQL事務處理 /* MYSQL的事務處理主要有兩種方法。 一、用begin,rollback,commit來實現 begin 開始一個事務 rollback 事務回滾 commit 事務確認 二、直接用set來改變mysql的自動提交模式 MYSQL默認是自動提交的,也就是你提交一個QUERY,它就直接執行!咱們能夠經過 set autocommit=0 禁止自動提交 set autocommit=1 開啓自動提交 來實現事務的處理。 當你用 set autocommit=0 的時候,你之後全部的SQL都將作爲事務處理,直到你用commit確認或rollback結束。 注意當你結束這個事務的同時也開啓了個新的事務!按第一種方法只將當前的做爲一個事務! 我的推薦使用第一種方法! MYSQL中只有INNODB和BDB類型的數據表才能支持事務處理!其餘的類型是不支持的! ***:通常MYSQL數據庫默認的引擎是MyISAM,這種引擎不支持事務!若是要讓MYSQL支持事務,能夠本身手動修改: 方法以下:1.修改c:\appserv\mysql\my.ini文件,找到skip-InnoDB,在前面加上#,後保存文件。 2.在運行中輸入:services.msc,重啓mysql服務。 3.到phpmyadmin中,mysql->show engines;(或執行mysql->show variables like 'have_%'; ),查看InnoDB爲YES,即表示數據庫支持InnoDB了。 也就說明支持事務transaction了。 4.在建立表時,就能夠爲Storage Engine選擇InnoDB引擎了。若是是之前建立的表,可使用mysql->alter table table_name type=InnoDB; 或 mysql->alter table table_name engine=InnoDB;來改變數據表的引擎以支持事務。 */ /*************** transaction--1 ***************/ $conn = mysql_connect('localhost','root','root') or die ("數據鏈接錯誤!!!"); mysql_select_db('test',$conn); mysql_query("set names 'GBK'"); //使用GBK中文編碼; //開始一個事務 mysql_query("BEGIN"); //或者mysql_query("START TRANSACTION"); $sql = "INSERT INTO `user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')"; $sql2 = "INSERT INTO `user` (`did`, `username`, `sex`) VALUES (NULL, 'test1', '0')";//這條我故意寫錯 $res = mysql_query($sql); $res1 = mysql_query($sql2); if($res && $res1){ mysql_query("COMMIT"); echo '提交成功。'; }else{ mysql_query("ROLLBACK"); echo '數據回滾。'; } mysql_query("END"); /**************** transaction--2 *******************/ /*方法二*/ mysql_query("SET AUTOCOMMIT=0"); //設置mysql不自動提交,需自行用commit語句提交 $sql = "INSERT INTO `user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')"; $sql2 = "INSERT INTO `user` (`did`, `username`, `sex`) VALUES (NULL, 'test1', '0')";//這條我故意寫錯 $res = mysql_query($sql); $res1 = mysql_query($sql2); if($res && $res1){ mysql_query("COMMIT"); echo '提交成功。'; }else{ mysql_query("ROLLBACK"); echo '數據回滾。'; } mysql_query("END"); //事務處理完時別忘記mysql_query("SET AUTOCOMMIT=1");自動提交 /******************對於不支持事務的MyISAM引擎數據庫可使用表鎖定的方法:********************/ //MyISAM & InnoDB 都支持, /* LOCK TABLES能夠鎖定用於當前線程的表。若是表被其它線程鎖定,則形成堵塞,直到能夠獲取全部鎖定爲止。 UNLOCK TABLES能夠釋放被當前線程保持的任何鎖定。當線程發佈另外一個LOCK TABLES時,或當與服務器的鏈接被關閉時,全部由當前線程鎖定的表被隱含地解鎖。 */ mysql_query("LOCK TABLES `user` WRITE");//鎖住`user`表 $sql = "INSERT INTO `user` (`id`, `username`, `sex`) VALUES (NULL, 'test1', '0')"; $res = mysql_query($sql); if($res){ echo '提交成功。!'; }else{ echo '失敗!'; } mysql_query("UNLOCK TABLES");//解除鎖定 MyISAM 是MySQL中默認的存儲引擎,通常來講不是有太多人關心這個東西。決定使用什麼樣的存儲引擎是一個很tricky的事情,可是仍是值咱們去研究一下,這裏的文章只考慮 MyISAM 和InnoDB這兩個,由於這兩個是最多見的。 下面先讓咱們回答一些問題: ◆你的數據庫有外鍵嗎? ◆你須要事務支持嗎? ◆你須要全文索引嗎? ◆你常用什麼樣的查詢模式? ◆你的數據有多大? myisam只有索引緩存 innodb不分索引文件數據文件 innodb buffer myisam只能管理索引,在索引數據大於分配的資源時,會由操做系統來cache;數據文件依賴於操做系統的cache。innodb無論是索引仍是數據,都是本身來管理 思考上面這些問題可讓你找到合適的方向,但那並非絕對的。若是你須要事務處理或是外鍵,那麼InnoDB 多是比較好的方式。若是你須要全文索引,那麼一般來講 MyISAM是好的選擇,由於這是系統內建的,然而,咱們其實並不會常常地去測試兩百萬行記錄。因此,就算是慢一點,咱們能夠經過使用Sphinx從 InnoDB中得到全文索引。 數據的大小,是一個影響你選擇什麼樣存儲引擎的重要因素,大尺寸的數據集趨向於選擇InnoDB方式,由於其支持事務處理和故障恢復。數據庫的在小決定了 故障恢復的時間長短,InnoDB能夠利用事務日誌進行數據恢復,這會比較快。而MyISAM可能會須要幾個小時甚至幾天來幹這些事,InnoDB只須要 幾分鐘。 您操做數據庫表的習慣可能也會是一個對性能影響很大的因素。好比: COUNT() 在 MyISAM 表中會很是快,而在InnoDB 表下可能會很痛苦。而主鍵查詢則在InnoDB下會至關至關的快,但須要當心的是若是咱們的主鍵太長了也會致使性能問題。大批的inserts 語句在 MyISAM下會快一些,可是updates 在InnoDB 下會更快一些——尤爲在併發量大的時候。 因此,到底你檢使用哪個呢?根據經驗來看,若是是一些小型的應用或項目,那麼MyISAM 也許會更適合。固然,在大型的環境下使用 MyISAM 也會有很大成功的時候,但卻不老是這樣的。若是你正在計劃使用一個超大數據量的項目,並且須要事務處理或外鍵支持,那麼你真的應該直接使用 InnoDB方式。但須要記住InnoDB 的表須要更多的內存和存儲,轉換100GB 的MyISAM 表到InnoDB 表可能會讓你有很是壞的體驗。 =========================================================== MyISAM:這個是默認類型,它是基於傳統的ISAM類型,ISAM是 Indexed Sequential Access Method (有索引的順序訪問方法) 的縮寫,它是存儲記錄和文件的標準方法.與其餘存儲引擎比較,MyISAM具備檢查和修復表格的大多數工具. MyISAM表格能夠被壓縮,並且它們支持全文搜索.它們不是事務安全的,並且也不支持外鍵。若是事物回滾將形成不徹底回滾,不具備原子性。若是執行大量 的SELECT,MyISAM是更好的選擇。 InnoDB:這種類型是事務安全的.它與BDB類型具備相同的特性,它們還支持外鍵.InnoDB表格速度很快.具備比BDB還豐富的特性,所以若是需 要一個事務安全的存儲引擎,建議使用它.若是你的數據執行大量的INSERT或UPDATE,出於性能方面的考慮,應該使用InnoDB表, 對於支持事物的InnoDB類型的標,影響速度的主要緣由是AUTOCOMMIT默認設置是打開的,並且程序沒有顯式調用BEGIN 開始事務,致使每插入一條都自動Commit,嚴重影響了速度。能夠在執行sql前調用begin,多條sql造成一個事物(即便autocommit打 開也能夠),將大大提升性能。 =============================================================== InnoDB和MyISAM是在使用MySQL最經常使用的兩個表類型,各有優缺點,視具體應用而定。下面是已知的二者之間的差異,僅供參考。 innodb InnoDB 給 MySQL 提供了具備事務(commit)、回滾(rollback)和崩潰修復能力 (crash recovery capabilities)的事務安全(transaction-safe (ACID compliant))型表。 InnoDB 提供了行鎖(locking on row level),提供與 Oracle 類型一致的不加鎖讀取(non- locking read in SELECTs)。這些特性均提升了多用戶併發操做的性能表現。在InnoDB表中不須要擴大鎖定 (lock escalation),由於 InnoDB 的列鎖定(row level locks)適宜很是小的空間。 InnoDB 是 MySQL 上第一個提供外鍵約束(FOREIGN KEY constraints)的表引擎。 InnoDB 的設計目標是處理大容量數據庫系統,它的 CPU 利用率是其它基於磁盤的關係數據庫引擎所不能比的。在技術上,InnoDB 是一套放在 MySQL 後臺的完整數據庫系統,InnoDB 在主內存中創建其專用的緩衝池用於高速緩衝數據和索引。 InnoDB 把數據和索引存放在表空間裏,可能包含多個文件,這與其它的不同,舉例來講,在 MyISAM 中,表被存放在單獨的文件中。InnoDB 表的大小隻受限於操做系統的文件大小,通常爲 2 GB。 InnoDB全部的表都保存在同一個數據文件 ibdata1 中(也多是多個文件,或者是獨立的表空間文件),相對來講比較很差備份,免費的方案能夠是拷貝數據文件、備份 binlog,或者用 mysqldump。 MyISAM MyISAM 是MySQL缺省存貯引擎 . 每張MyISAM 表被存放在三個文件 。frm 文件存放表格定義。 數據文件是MYD (MYData) 。 索引文件是 MYI (MYIndex) 引申。 由於MyISAM相對簡單因此在效率上要優於InnoDB..小型應用使用MyISAM是不錯的選擇. MyISAM表是保存成文件的形式,在跨平臺的數據轉移中使用MyISAM存儲會省去很多的麻煩 如下是一些細節和具體實現的差異: 1.InnoDB不支持FULLTEXT類型的索引。 2.InnoDB 中不保存表的具體行數,也就是說,執行select count(*) from table時,InnoDB要掃描一遍整個表來計算有多少行,可是MyISAM只要簡單的讀出保存好的行數便可。注意的是,當count(*)語句包含 where條件時,兩種表的操做是同樣的。 3.對於AUTO_INCREMENT類型的字段,InnoDB中必須包含只有該字段的索引,可是在MyISAM表中,能夠和其餘字段一塊兒創建聯合索引。 4.DELETE FROM table時,InnoDB不會從新創建表,而是一行一行的刪除。 5.LOAD TABLE FROM MASTER操做對InnoDB是不起做用的,解決方法是首先把InnoDB表改爲MyISAM表,導入數據後再改爲InnoDB表,可是對於使用的額外的InnoDB特性(例如外鍵)的表不適用。 另外,InnoDB表的行鎖也不是絕對的,若是在執行一個SQL語句時MySQL不能肯定要掃描的範圍,InnoDB表一樣會鎖全表,例如 update table set num=1 where name like 「%aaa%」 任何一種表都不是萬能的,只用恰當的針對業務類型來選擇合適的表類型,才能最大的發揮MySQL的性能優點。 =============================================================== 如下是InnoDB和MyISAM的一些聯繫和區別! 1. 4.0以上mysqld都支持事務,包括非max版本。3.23的須要max版本mysqld才能支持事務。 2. 建立表時若是不指定type則默認爲myisam,不支持事務。 能夠用 show create table tablename 命令看錶的類型。 2.1 對不支持事務的表作start/commit操做沒有任何效果,在執行commit前已經提交,測試: 執行一個msyql: use test; drop table if exists tn; create table tn (a varchar(10)) type=myisam; drop table if exists ty; create table ty (a varchar(10)) type=innodb; begin; insert into tn values(‘a’); insert into ty values(‘a’); select * from tn; select * from ty; 都能看到一條記錄 執行另外一個mysql: use test; select * from tn; select * from ty; 只有tn能看到一條記錄 而後在另外一邊 commit; 才都能看到記錄。 3. 能夠執行如下命令來切換非事務表到事務(數據不會丟失),innodb表比myisam表更安全: alter table tablename type=innodb; 3.1 innodb表不能用repair table命令和myisamchk -r table_name 但能夠用check table,以及mysqlcheck [OPTIONS] database [tables] ============================================================== mysql中使用select for update的必須針對InnoDb,而且是在一個事務中,才能起做用。 select的條件不同,採用的是行級鎖仍是表級鎖也不同。 轉http://www.neo.com.tw/archives/900 的說明 因爲InnoDB 預設是Row-Level Lock,因此只有「明確」的指定主鍵,MySQL 纔會執行Row lock (只鎖住被選取的資料例) ,不然MySQL 將會執行Table Lock (將整個資料表單給鎖住)。 舉個例子: 假設有個表單products ,裏面有id 跟name 二個欄位,id 是主鍵。 例1: (明確指定主鍵,而且有此筆資料,row lock) SELECT * FROM products WHERE id=’3′ FOR UPDATE; 例2: (明確指定主鍵,若查無此筆資料,無lock) SELECT * FROM products WHERE id=’-1′ FOR UPDATE; 例2: (無主鍵,table lock) SELECT * FROM products WHERE name=’Mouse’ FOR UPDATE; 例3: (主鍵不明確,table lock) SELECT * FROM products WHERE id<>’3′ FOR UPDATE; 例4: (主鍵不明確,table lock) SELECT * FROM products WHERE id LIKE ’3′ FOR UPDATE; 注1: FOR UPDATE 僅適用於InnoDB,且必須在交易區塊(BEGIN/COMMIT)中才能生效