用新PHP外掛程式實現MySQL為基礎的事務

來源:互聯網
上載者:User
 

    交易處理支援很長時間以來一直是大多數MySQL開發人員的心愿,隨著MySQL 4.0的發布,這個心愿最後終於得以實現。MySQL 4.0後不久,擁有一個新的MySQL外掛程式的PHP 5.x也發布了。這個新外掛程式,MySQL Improved,使得PHP開發人員通過利用本地的PHP函數,獲得了這些新的交易處理能力。這篇簡短的教程將向你說明怎樣利用這些新的MySQLi函數,用PHP實現以MySQL為基礎的事務。

  概要

  如果你還不知道,那麼我可以告訴你,事務只是一組SQL語句,通常因為它們是彼此相互依賴的,所以要在全有或全無(all-or-nothing)的模式下執行。只有當所有組成的語句都執行成功了,一個事務才算是成功了;任何一個語句中的失敗應該都會導致系統“復原”到它先前的狀態,以避免資料連線/崩潰問題。

  對於這一點,兩個銀行帳戶間的轉帳是一個很好的例子。在資料庫級,這樣的轉帳包括兩個步驟:首先,從源帳戶中扣除轉帳的金額,然後將其加到目標帳戶中。如果在第二步中發生了錯誤,那麼第一步就必須被取消,以避免不相符的情況(和憤怒的客戶聚眾滋事)。事務安全系統將自動地撤到系統先前的“快照”。

  大多數資料庫(包括MySQL)通過一個命令的組合來完成這個:

  * START TRANSACTION命令標誌著一個新的事務組的開始。它後面常接一系列的SQL命令。

  * COMMIT命令標誌著一個事務組的結束,表示事務期間做的所有改變應該被提交或者使之永久化。

  * ROLLBACK命令標誌著一個事務組的結束,表示事務期間所做的所有改變應該被撤消。

  PHP中的交易處理函數

  PHP中的MySQLi外掛程式引進了新的函數,協助開發人員利用MySQL的交易處理能力。實質上,這些函數對等地被叫做SQL START TRANSACTION,COMMIT和 ROLLBACK命令。列表A為你展示了一個例子,列表A:

  // connect to database

  $dbh = mysqli_connect($host, $user, $pass, $db);

  // turn off auto-commit

  mysqli_autocommit($dbh, FALSE);

  // run query 1

  $result = mysqli_query($dbh, $query1);

  if ($result !== TRUE) {

  mysqli_rollback($dbh); // if error, roll back transaction

  }

  // run query 2

  $result = mysqli_query($dbh, $query2);

  if ($result !== TRUE) {

  mysqli_rollback($dbh); // if error, roll back transaction

  }

  // and so on...

  // assuming no errors, commit transaction

  mysqli_commit($dbh);

  // close connection

  mysqli_close($dbh);

  ?>

  在PHP 中執行一項事務有三個基本的步驟:

  * 第一步是始終關掉資料庫的“auto-commit”,它實質上意味著系統在你作出改變時就儲存它們。這一點是很重要的,因為在一個交易處理環境中,你應該只有在確定了所有交易處理的“unit”都成功完成了以後,才儲存你所做的改變。你可以通過mysqli_autocommit()函數關掉資料庫的自動認可。

  * 接下來,通過mysqli_query()函數,繼續用通常的方法進行INSERT、UPDATE和/或DELETE查詢。檢驗每一個查詢返回的值,弄清楚它是否成功了是很重要的。如果其中任何一個查詢失敗了,mysqli_rollback()函數就會被用來將系統返回到事務進行之前的狀態。

  * 假設組成事務組的所有命令都成功執行了,就要用mysqli_commit()函數將變化儲存到資料庫系統。請注意,一旦這個函數被調用,事務就不能被撤消了。

  工作執行個體

  要瞭解這個在實踐中是怎麼工作的,讓我們回到前面討論過的銀行轉帳的例子.我們假設你的任務是建立一個簡單的Web應用程式,讓使用者在他們的銀行帳戶間轉帳。我們再進一步假設一個單獨使用者的帳戶儲存在一個MySQL資料庫中,如下所示:

  mysql> SELECT * FROM accounts;

  +----+------------+---------+

  | id | label | balance |

  +----+------------+---------+

  | 1 | Savings #1 | 1000 |

  | 2 | Current #1 | 2000 |

  | 3 | Current #2 | 3000 |

  +----+------------+---------+

  3 rows in set (0.34 sec)

  現在,需要建立一個簡單的介面,使使用者能夠輸入一個現金數額,實現從一個帳戶到另一個的轉帳。實際的“交易”將用兩個UPDATE語句來執行,一個將轉帳金額從源帳戶取出,即借方,另一個將轉帳金額記入目標帳戶,即貸方。假設我們所做的是在帳戶之間進行轉帳,那麼所有帳戶的可用結餘總額($6000)應該一直保持不變。

  列表B顯示了可能的代碼,列表 B:

  // connect to database

  $dbh = mysqli_connect("localhost", "user", "pass", "test")

  or die("Cannot connect");

  // turn off auto-commit

  mysqli_autocommit($dbh, FALSE);

  // look for a transfer

  if ($_POST['submit'] && is_numeric($_POST['amt'])) {

  // add $$ to target account

  $result = mysqli_query($dbh, "UPDATE accounts SET

  balance = balance + " . $_POST['amt'] . " WHERE id = " . $_POST['to']);

  if ($result !== TRUE) {

  mysqli_rollback($dbh); // if error, roll back transaction

  }

  // subtract $$ from source account

  $result = mysqli_query($dbh, "UPDATE accounts

  SET balance = balance - " . $_POST['amt'] .

  " WHERE id = " . $_POST['from']);

  if ($result !== TRUE) {

  mysqli_rollback($dbh); // if error, roll back transaction

  }

  // assuming no errors, commit transaction

  mysqli_commit($dbh);

  }

  // get account balances

  // save in array, use to generate form

  $result = mysqli_query($dbh, "SELECT * FROM accounts");

  while ($row = mysqli_fetch_assoc($result)) {

  $accounts[] = $row;

  }

  // close connection

  mysqli_close($dbh);

  ?>

  像你所看到的那樣,指令碼以串連資料庫和關閉自動認可開始。然後執行一個SELECT查詢,檢索所有帳戶的現金收支,接著構造一個有下拉式介面的表格,選擇交易要用到的來源/目標帳戶。圖表A顯示了最初的表格。

  最初的表格

  一旦表格完成並提交後,兩個UPDATE查詢就開始實際執行借和貸操作。注意每一個查詢的尾端都帶有一個mysqli_rollback(),如果查詢失敗的話,它將被啟用。假設沒有查詢失敗的話,新的收支表就通過調用mysqli_commit()儲存到資料庫中。那時資料庫連接就被關閉。

  你可以自己試一下,從Savings #1轉$500到Current #2。一旦你執行轉帳之後,你將看到表B所示的平衡表的新結果。

  交易完成之後的狀況。

  提示:當然,這隻是一個簡單的雙命令的事務。通常,當有許多SQL語句要一起執行的時候,你可以用這種事務模型,一個語句的失敗對其他語句有串聯的影響。在這些情況下,你會發現將mysqli_query()和mysqli_rollback()的調用壓縮到一個單獨的使用者自訂的函數中,需要的時候調用它會更加簡便。

  正如你所看到的那樣,用PHP和MySQL執行一個交易處理模型可以使你的MySQL資料庫對查詢執行的錯誤更穩固。但是,在你開始動手重寫代碼和使用這個模型之前,值得注意的是,事務確實會增加系統效能管理的消耗,所以,在實現這個模型之前,做一個成本效益分析始終是個好主意。

 

(轉自:http://blog.sina.com.cn/s/blog_59be01000100ck35.html)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.