MYSQL事務之學習筆記

來源:互聯網
上載者:User

由於項目設計裡面,牽扯到了金錢的轉移,於是就要用到MYSQL的交易處理,來保證一組處理結果的正確性

用了事務,就不可避免的要犧牲一部分速度,來保證資料的正確性。

只有InnoDB支援事務

事務 ACID Atomicity(原子性)、Consistency(穩定性)、Isolation(隔離性)、Durability(可靠性)

1、事務的原子性
一組事務,要麼成功;要麼撤回。

2、穩定性
有非法資料(外鍵約束之類),事務撤回。

3、隔離性
事務獨立運行。
一個交易處理後的結果,影響了其他事務,那麼其他事務會撤回。
事務的100%隔離,需要犧牲速度。

4、可靠性
軟、硬體崩潰後,InnoDB資料表驅動會利用記錄檔重構修改。
可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項 決定什麼時候吧事務儲存到日誌裡。
開啟事務
 START TRANSACTION 或 BEGIN

提交事務(關閉事務)
 COMMIT

放棄事務(關閉事務)
 ROLLBACK

折返點
 SAVEPOINT adqoo_1
 ROLLBACK TO SAVEPOINT adqoo_1
 發生在折返點 adqoo_1 之前的事務被提交,之後的被忽略

事務的終止

設定“自動認可”模式
 SET AUTOCOMMIT = 0
 每條SQL都是同一個事務的不同命令,之間由 COMMIT 或 ROLLBACK隔開
 掉線後,沒有 COMMIT 的事務都被放棄

事務鎖定模式

系統預設: 不需要等待某事務結束,可直接查詢到結果,但不能再進行修改、刪除。
缺點:查詢到的結果,可能是已經到期的。
優點:不需要等待某事務結束,可直接查詢到結果。

需要用以下模式來設定鎖定模式

1、SELECT …… LOCK IN SHARE MODE(共用鎖定)
查詢到的資料,就是資料庫在這一時刻的資料(其他已commit事務的結果,已經反應到這裡了)
SELECT 必須等待,某個事務結束後才能執行

2、SELECT …… FOR UPDATE(排它鎖)
例如 SELECT * FROM tablename WHERE id<200
那麼id<200的資料,被查詢到的資料,都將不能再進行修改、刪除、SELECT …… LOCK IN SHARE MODE操作
一直到此事務結束

共用鎖定 和 排它鎖 的區別:在於是否阻斷其他客戶發出的 SELECT …… LOCK IN SHARE MODE命令

3、INSERT / UPDATE / DELETE
所有關聯資料都會被鎖定,加上排它鎖

4、防插入鎖
例如 SELECT * FROM tablename WHERE id>200
那麼id>200的記錄無法被插入

5、死結
自動識別死結
先進來的進程被執行,後來的進程收到出錯訊息,並按ROLLBACK方式復原
innodb_lock_wait_timeout = n 來設定最長等待時間,預設是50秒

 

事務隔離模式

SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL
READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE
1、不帶SESSION、GLOBAL的SET命令
 只對下一個事務有效
2、SET SESSION
 為當前會話設定隔離模式
3、SET GLOBAL
 為以後建立的所有MYSQL串連設定隔離模式(當前串連不包括在內)

隔離模式

   READ UNCOMMITTED
 不隔離SELECT
 其他事務未完成的修改(未COMMIT),其結果也考慮在內

   READ COMMITTED
 把其他事務的 COMMIT 修改考慮在內
 同一個事務中,同一 SELECT 可能返回不同結果

   REPEATABLE READ(預設)
 不把其他事務的修改考慮在內,無論其他事務是否用COMMIT命令提交過
 同一個事務中,同一 SELECT 返回同一結果(前提是本事務,不修改)

   SERIALIZABLE
 和REPEATABLE READ類似,給所有的SELECT都加上了 共用鎖定

出錯處理
 根據出錯資訊,執行相應的處理

最後看看PHP + MySQL事務操作的代碼示範:

實際LAMP應用中,一般PHP使用AdoDB操作MySQL,下面給出AdoDB相應的代碼方便大家查閱:

-------------------------------------------------------------------------------

 代碼如下 複製代碼

<?php
// ...

$adodb->startTrans();

//實際,getOne所調用的查詢也可以直接放到rowLock來進行,這裡只是為了示範效果能更明顯些。

$adodb->rowLock('book', 'book_id = 123');

$bookNumber = $adodb->getOne("SELECT book_number FROM book WHERE  book_id = 123");

$adodb->execute("UPDATE book SET book_number = book_number - 1 WHERE  book_id = 123");

$adodb->completeTrans();

// ...
?>

-------------------------------------------------------------------------------

其中,rowLock的方法就是調用的FOR UPDATE來實現的行鎖,你可能會想把“FOR UPDATE”直接寫到$adodb->getOne()調用的那條SQL語句裡面去實現行鎖的功能,不錯,那樣確實可以,但是並不是所有的資料庫都使用“FOR UPDATE”文法來實現行鎖功能,比如Sybase使用“HOLDLOCK”的文法來實現行鎖功能,所以為了你的資料庫抽象層保持可移植性,我還是勸你用rowLock來實現行鎖功能

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.