當前位置:編程學習大全網 - 源碼下載 - 如何在mysql 的存儲過程中使用事務

如何在mysql 的存儲過程中使用事務

6.7 MySQL 事務與鎖定命令

6.7.1 BEGIN/COMMIT/ROLLBACK 句法

缺省的,MySQL 運行在 autocommit 模式。這就意味著,當妳執行完壹個更新時,MySQL 將立刻將更新存儲到磁盤上。

如果妳使用事務安全表 (例如 InnoDB、BDB),通過下面的命令,妳可以設置 MySQL 為非 autocommit 模式:

SET AUTOCOMMIT=0

在此之後,妳必須使用 COMMIT 來存儲妳的更改到磁盤上,或者使用 ROLLBACK ,如果妳希望忽略從妳的事務開始所做的更改。

如果妳希望為壹系列語句從 AUTOCOMMIT 模式轉換,妳可以使用 START TRANSACTION 或 BEGIN 或 BEGIN WORK 語句:

START TRANSACTION;

SELECT @A:=SUM(salary) FROM table1 WHERE type=1;

UPDATE table2 SET summmary=@A WHERE type=1;

COMMIT;

START TRANSACTION 在 MySQL 4.0.11 中被加入;這是被推薦的開始壹個特別(ad-hoc)事務的方式,因為這是 ANSI SQL 句法。

註意,如果妳使用的是壹個非事務安全表,更改會立刻被存儲,不受 autocommit 模式狀態的約束。

當妳更新了壹個非事務表後,如果妳執行壹個 ROLLBACK,妳將得到壹個錯誤 (ER_WARNING_NOT_COMPLETE_ROLLBACK) 作為壹個警告。所有事務安全表將被恢復,但是非事務安全表將不會改變。

如果妳使用 START TRANSACTION 或 SET AUTOCOMMIT=0,妳應該使用 MySQL

二進制日誌做備份以代替老的更新日誌。事務處理被以壹個大塊形式存儲在二進制日誌中,在 COMMIT

上面,為了保護回滾的事務,而不是被存儲的。查看章節 4.9.4 二進制日誌。 如果您使用起動事務處理或集AUTOCOMMIT=0

,您應該使用MySQL 二進制日誌為備份代替更舊的更新日誌。 事務處理存儲在二進制登錄壹大塊,做,保證, 滾的事務處理不存儲。 參見部分4

。9.4 二進制日誌。

下列命令自動的結束壹個事務 (就好像妳在執行這個命令之前,做了壹個 COMMIT):

命令 命令 命令

ALTER TABLE BEGIN CREATE INDEX

DROP DATABASE DROP TABLE RENAME TABLE

TRUNCATE

妳可以使用 SET TRANSACTION ISOLATION LEVEL ... 改變事務的隔離級。查看章節 6.7.3 SET TRANSACTION 句法。

6.7.2 LOCK TABLES/UNLOCK TABLES 句法

LOCK TABLES tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}

[, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE} ...]

...

UNLOCK TABLES

LOCK TABLES 為當前線程鎖定表。UNLOCK TABLES 釋放當前線程擁有的所有鎖定。當線程發出另壹個 LOCK TABLES,或當與服務器的連接被關閉時,被當前線程鎖定的所有表將被自動地解鎖。

為了在 MySQL 4.0.2 使用 LOCK TABLES ,妳必須擁有壹個全局的 LOCK TABLES 權限和壹個在相關表上的

SELECT 權限。在 MySQL 3.23 中,妳對該表需要有 SELECT、insert、DELETE 和 UPDATE 權限。

使用 LOCK TABLES 的主要原因是,仿效事務處理或在更新表時得到更快的速度。此後會有更詳細的描述。

如果壹個線程在壹個表上得到壹個 READ 鎖,該線程 (和所有其它線程) 只能從表中讀取。如果壹個線程在壹個表上得到壹個 WRITE 鎖,那麽只有擁有這個鎖的線程可以從表中讀取和寫表。其它的線程被阻塞。

READ LOCAL 和 READ 之間的不同就在於,當鎖被加載時,READ LOCAL 允許非沖突(non-conflicting) INSERT 語句執行。如果當妳加載著鎖時從 MySQL 外部操作數據庫文件,這將仍不能被使用。

當妳使用 LOCK TABLES 是地,妳必須鎖定所有妳將使用的表,並且必須使用與妳的查詢中將使用的別名相同!如果妳在壹個查詢中多次使用壹個表(用別名),妳必須為每壹個別名獲得壹個鎖。

WRITE 鎖通過比 READ 鎖有更高的權限,以確保更新被盡快地處理。這就意味著,如果壹個線程獲得壹個 READ

鎖,而同時另外壹個線程請求壹個 WRITE 鎖,並發的 READ 鎖請求將等待直到 WRITE 線程得到了鎖並釋放了它。妳可以使用

LOW_PRIORITY WRITE 鎖,當該線程在等待 WRITE 鎖時,它將允許其它的線程獲得 READ 鎖。 妳應該只使用

LOW_PRIORITY WRITE 鎖,如果妳確信這將是最後壹次,當沒有線程將擁有 READ 鎖。

LOCK TABLES 工作如下:

以內部定義的次序排序所有被鎖定的表 (從用戶立場說,該次序是不明確的)。

如果壹個表被以壹個讀鎖和壹個寫鎖鎖定,將寫鎖放在讀鎖之前。

壹次只鎖定壹個表,只到線程得到所有的鎖定。

這個方案是為了確保,表鎖定死鎖釋放。 對於這個模式妳仍然有些其它事情需要知道:

如果妳對壹個表使用壹個 LOW_PRIORITY WRITE 鎖定,這就意味著,MySQL 將等待這個鎖,直到沒有線程請求壹個 READ

鎖。當線程得到了 WRITE 鎖,並等待獲得鎖定表列表中的下壹個表的鎖定時,其它所有的線程將等待 WRITE

鎖被釋放。如果這在妳的應用程序中會引起壹個嚴重的問題,妳應該考慮將妳的某些表轉換為事務安全表。

妳可以使用 KILL 安全地殺死壹個正在表鎖定的線程。查看章節 4.5.5 KILL 句法。

註意,妳不應該 鎖定妳正在對其使用 INSERT DELAYED 的表。這是因為,在這種情況下,INSERT 是通過單獨的線程完成的。

通常,妳不需要鎖定任何表,因為所有單 UPDATE 語句都是原子的;其它的線程無法幹擾當前執行的 SQL 語句。當妳無論如何希望鎖定表時,這裏有壹些情況:

如果妳在壹束表上運行許多操作,鎖定妳將要使用的表,這會更快壹些。當然有不利的方面,其它線程將不能更新壹個 READ

鎖的表,並且沒有其它線程要以讀取壹個 WRITE 鎖的表。 在 LOCK TABLES 下,某些事運行得更快壹些的原因是,MySQL

將不會轉儲清除被鎖定表鍵高速緩沖,直到 UNLOCK TABLES 被調用 (通常鍵高速緩沖在每個 SQL 語句後都會被轉儲清除)。這將加速在

MyISAM 表上的插入、更新、刪除。

如果妳在 MySQL 中正在使用壹個不支持事務的存儲引擎,如果妳希望能確保沒有其它的線程會出現在壹個 SELECT 和 壹個 UPDATE 之間,妳必須使用 LOCK TABLES 。下面的示例顯示為了安全地執行,這裏需要LOCK TABLES :

mysql> LOCK TABLES trans READ, customer WRITE;

mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;

mysql> UPDATE customer SET total_value=sum_from_previous_statement

-> WHERE customer_id=some_id;

mysql> UNLOCK TABLES;

不使用 LOCK TABLES,將可能發生在 SELECT 和 UPDATE 語句執行期間有另外壹個線程可能在 trans 表中插入壹行新記錄。

通過使用遞增更新 (UPDATE customer SET value=value+new_value) 或 LAST_INSERT_ID() 函數,妳可以在很多情況下避免使用 LOCK TABLES。

妳也可以使用用戶級鎖定函數 GET_LOCK() 和 RELEASE_LOCK() 解決壹些情況,這些鎖被保存在服務器上的壹個哈希表中,並以

pthread_mutex_lock() 和 pthread_mutex_unlock() 實現以獲得高速度。查看章節 6.3.6.2

輔助功能函數。

查看章節 5.3.1 MySQL 如何鎖定表,以獲取關於鎖定方案的更多信息。

妳可以使用 FLUSH TABLES WITH READ LOCK 命令以讀鎖鎖定所有數據庫中的所有表。查看章節 4.5.3 FLUSH 句法。如果妳有壹個可以及時建立文件快照的文件系統,例如 Veritas,這將是得到備份的非常方便方式。

註意:LOCK TABLES 不是事務安全的,在嘗試鎖定壹個表之前,將自動地提交所有的活動事務。

6.7.3 SET TRANSACTION 句法

SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL

{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

設置全局的、整個會話或下壹個事務的事務隔離級。

缺省行為是設置下壹個(未啟動的)事務的隔離級。如果妳使用 GLOBAL

關鍵詞,語句為所有在那個點上建立的新連接設置默認的全局事務隔離級。為了這樣做,妳需要有 SUPER 權限。使用 SESSION

關鍵詞為當前連接所有將來執行的事務設置默認的事務隔離級。

妳可以使用 --transaction-isolation=... 為 mysqld 設置默認的全局隔離級。查看章節 4.1.1 mysqld 命令行選項

  • 上一篇:向女生表白的話真誠的句子
  • 下一篇:webrtc linphone 到底哪個
  • copyright 2024編程學習大全網