程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 關於數據庫(MySQL)事務

關於數據庫(MySQL)事務

編輯:MySQL綜合教程

關於數據庫(MySQL)事務


事務是由一步或幾步數據庫操作序列組成邏輯執行單元,這系列操作要麼全部執行,要麼全部放棄執行。

因為做php開發接觸較多的數據庫是MySQL數據庫,所以本文主要和大家分享一些關於MySQL數據事務的相關知識,首先得提一下,在MySQL數據庫中,支持數據庫事務的暫時只有BDB,InnoDB這兩種的引擎類型,所以如果你需要做事務相關方面的開發,必須先將數據表設置為正確的引擎類型,如InnoDB(這又是MySQL數據庫中比較常用的引擎類型)。下面以InnoDB表類型為例簡單說一下MySQL中的事務。

先來明確一下事務涉及的相關知識:

事務都應該具備ACID特征。所謂ACID是Atomic(原子性),Consistent(一致性),Isolated(隔離性),Durable(持續性)四個詞的首字母所寫,下面以“銀行轉帳”為例來分別說明一下它們的含義:

原子性:組成事務處理的語句形成了一個邏輯單元,不能只執行其中的一部分。對於其數據修改,要麼全都執行,要麼全都不執行。如果系統只執行這些操作的一個子集,則可能會破壞事務的總體目標。換句話說,事務是應用中最小的執行單位,就如原子是自然界最小顆粒,具有不可再分的特征一樣。事務是應用中不可再分的最小邏輯執行體。比如:銀行轉帳過程中,必須同時從一個帳戶減去轉帳金額,並加到另一個帳戶中,只改變一個帳戶是不合理的。

一致性:在事務處理執行前後,MySQL數據庫是一致的。也就是說,事務應該正確的轉換系統狀態。數據庫原來有什麼樣的約束,事務執行之後還需要存在這樣的約束,所有規則都必須應用於事務的修改,以保持所有數據的完整性。事務結束時,所有的內部數據結構(如 B 樹索引或雙向鏈表)、完整性約束(索引、主鍵)都必須是一致的。一致性是通過原子性來保證的。比如:銀行轉帳過程中,要麼轉帳金額從一個帳戶轉入另一個帳戶,要麼兩個帳戶都不變,沒有其他的情況。

隔離性:事務查看數據時數據所處的狀態,要麼是另一並發事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會查看中間狀態的數據。當事務可序列化時將獲得最高的隔離級別。隔離性是事務機制裡相對來說,比較復雜的,一個事務處理對另一個事務處理沒有影響。就是說任何事務都不可能看到一個處在不完整狀態下的事務。比如說,銀行轉帳過程中,在轉帳事務沒有提交之前,另一個轉帳事務只能處於等待狀態。

持續性:持續性也稱為持久性,指事務一旦提交,對數據所做的任何改變,都要記錄到永久存儲器中,通常是保存進物理數據庫。就是說事務處理的結果能夠被永久保存下來。反過來說,事務應當能夠承受所有的失敗,包括服務器、進程、通信以及媒體失敗等等。比如:銀行轉帳過程中,轉帳後帳戶的狀態要能被保存下來。

下面說一個需要用到事務處理的具體生活實例

這裡以“網上購書”為例。先假設一下問題的背景:網上購書,某書(MySQL數據庫編號為123)只剩最後一本,而這個時候,兩個用戶對這本書幾乎同時發出了購買請求,讓我們看看整個過程:

在具體分析之前,先來看看此次實例所用到的數據表的定義:

create table book(  
book_id unsigned int(10) not null auto_increment,  
book_name varchar(100) not null,  
book_price float(5,2) not null, #我假設每本書的價格不會超過999.99元  
book_number int(10) not null,  
primary key (book_id)  
)/*www.phpernote.com*/
type = innodb;

對於用戶甲來說,他的動作稍微比乙快一點點,其購買過程所觸發的動作大致是這樣的:

1. SELECT book_number FROM book WHERE book_id = 123;

book_number大於零,確認購買行為並更新book_number

2. UPDATE book SET book_number = book_number - 1 WHERE book_id = 123;

購書成功

而對於用戶乙來說,他的動作稍微比甲慢一點點,其購買過程所觸發的動作和甲相同:

1. SELECT book_number FROM book WHERE book_id = 123;

這個時候,甲剛剛進行完第一步的操作,還沒來得及做第二步操作,所以book_number一定大於零

2. UPDATE book SET book_number = book_number - 1 WHERE book_id = 123;

購書成功

表面上看甲乙的操作都成功了,他們都買到了書,但是庫存只有一本,他們怎麼可能都成功呢?再看看數據表裡book_number的內容,已經變成“-1”了,這當然是不能允許的(實際上,聲明這樣的列類型應該加上unsigned的屬性,以保證其不能為負,這裡是為了說明問題所以沒有這樣設置)

好了,問題陳述清楚了,再來看看怎麼利用事務來解決這個問題,打開MySQL手冊,可以看到想用事務來保護你的SQL正確執行其實很簡單,基本就是三個語句:開始,提交,回滾。

開始:START TRANSACTION或BEGIN語句可以開始一項新的事務

提交:COMMIT可以提交當前事務,是變更成為永久變更

回滾:ROLLBACK可以回滾當前事務,取消其變更

此外,SET AUTOCOMMIT = {0 | 1}可以禁用或啟用默認的autocommit模式,用於當前連接。

那是不是只要用事務語句包一下我們的SQL語句就能保證正確了呢?比如下面代碼:

BEGIN;  
SELECT book_number FROM book WHERE book_id = 123;  
// ...  
UPDATE book SET book_numberbook_number = book_number - 1 WHERE book_id = 123;  
COMMIT;

答案是否定了,這樣依然不能避免問題的發生,如果想避免這樣的情況,實際應該如下:

BEGIN;  
SELECT book_number FROM book WHERE book_id = 123 FOR UPDATE;  
// ...  
UPDATE book SET book_numberbook_number = book_number - 1 WHERE book_id = 123;  
COMMIT;

由於加入了FOR UPDATE,所以會在此條記錄上加上一個行鎖,如果此事務沒有完全結束,那麼其他的事務在使用SELECT ... FOR UPDATE請求的時候就會處於等待狀態,直到上一個事務結束,它才能繼續,從而避免了問題的發生,需要注意的是,如果你其他的事務使用的是不帶FOR UPDATE的SELECT語句,將得不到這種保護。

下面分享一個使用php連接MySQL並使用事務的源碼示例

mysql事務處理主要分為如下四大步

begin       開始一個事物
 
commit      事務確認

rollback    事務回滾
 
end         事務結束

<?php
$conn=mysql_connect('localhost','root','123456') or die ("數據連接錯誤!");
mysql_select_db('shop',$conn);
mysql_query("set names 'utf8'"); //使用utf8中文編碼;
//開始一個事務
mysql_query("BEGIN"); //或者mysql_query("START TRANSACTION");
$sql="INSERT INTO main (num) VALUES (123)";
$sql2="INSERT INTO main (num1) VALUES (456)";//這條我故意寫錯
//如果不用事務或者用的而不是innodb引擎則$sql會成功$sql2會失敗
//用事務如果其中一條出現錯誤那麼兩條數據都不會執行成功
$res=mysql_query($sql);
$res1=mysql_query($sql2);  
if($res&&$res1){
	mysql_query("COMMIT");
	echo '提交成功。';
}else{
	mysql_query("ROLLBACK");
	echo '數據回滾。';
}
mysql_query("END");

以上的相關內容就是對MySQL數據庫與事務的介紹,望你能有所收獲。

您可能感興趣的文章

  • Yii中的數據庫事務的使用方法小結
  • 改善數據庫性能 揭秘SQL優化技巧
  • 如何知道數據庫中那些執行的SQL語句比較慢
  • Navicat for mysql 遠程連接 mySql數據庫提示10061,1045錯誤的解決辦法
  • 總結MySQL數據庫服務器逐漸變慢的原因和解決辦法
  • 大流量網站該如何實現優化服務器、靜態化、數據庫優化、負載均衡以實現高負載
  • 學會設置MySQL數據庫的五個常用參數
  • windows環境下mysql數據庫的主從同步備份步驟

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved