MySQL事务处理与事务隔离(锁机制)
轉載:http://blog.csdn.net/qq_26525215/article/details/52146529
MySQL 事務處理
簡單介紹事務處理:
MySQL?事務主要用于處理操作量大,復雜度高的數據。?
比如說,在人員管理系統中,你刪除一個人員,你即需要刪除人員的基本資料,也要刪除和該人員相關的信息,如信箱,文章等等,這樣,這些數據庫操作語句就構成一個事務!
一個事務是一個連續的一組數據庫操作,就好像它是一個單一的工作單元進行。換言之,永遠不會是完整的事務,除非該組內的每個單獨的操作是成功的。如果在事務的任何操作失敗,則整個事務將失敗。
事務處理可以用來維護數據庫的完整性,保證成批的SQL語句要么全部執行,要么全部不執行
事務用來管理多條insert,update,delete語句
一般來說,事務是必須滿足4個條件(ACID):?
Atomicity(原子性)、Consistency(穩定性)、Isolation(隔離性)、Durability(可靠性)
1、事務的原子性:一組事務,要么成功;要么撤回。?
2、穩定性 : 有非法數據(外鍵約束之類),事務撤回。?
3、隔離性:事務獨立運行。一個事務處理后的結果,影響了其他事務,那么其他事務會撤回。事務的100%隔離,需要犧牲速度。?
4、可靠性:軟、硬件崩潰后,InnoDB數據表驅動會利用日志文件重構修改。可靠性和高速度不可兼得, innodb_flush_log_at_trx_commit選項 決定什么時候把事務保存到日志里。
開始一個事務
start transaction- 1
- 1
在MySQL中,事務開始使用COMMIT或ROLLBACK語句開始工作和結束。開始和結束語句的SQL命令之間形成了大量的事務。
COMMIT & ROLLBACK:?
這兩個關鍵字提交和回滾(撤銷事務)主要用于MySQL的事務。
當一個成功的事務完成后,發出COMMIT命令應使所有參與表的更改才會生效。
如果發生故障時,應發出一個ROLLBACK命令返回的事務中引用的每一個表到以前的狀態。
可以控制的事務行為稱為AUTOCOMMIT設置會話變量。如果AUTOCOMMIT設置為1(默認值),然后每一個SQL語句(在事務與否)被認為是一個完整的事務,并承諾在默認情況下,當它完成。 AUTOCOMMIT設置為0時,發出SET AUTOCOMMIT =0命令,在隨后的一系列語句的作用就像一個事務,直到一個明確的COMMIT語句時,沒有活動的提交。
Java中setAutoCommit(false)對應mysql中的“START TRANSACTION;”的功能
SQL代碼演示說明:
start transaction; delete from aa where id='7'; update aa set sname='aaaa' where id='5'; rollback;/*事務回滾-執行失敗*/ /*commit;提交事務-執行成功*/- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
說明:從”start transaction”開始 到 “bollback; 或 commit; ”,這中間的那么語句是一個整體,如果執行 “bollback”,那么這些動作都會回滾(撤消)。如果執行“commit”,就全部執行成功。
Java代碼演示:
@Testpublic void transactionDemo() throws ClassNotFoundException, SQLException{//1、加載連接器(驅動) Driver Class.forName("com.mysql.jdbc.Driver");//2、建立連接String url = "jdbc:mysql://127.0.0.1:3306/hncu?useUnicode=true&characterEncoding=utf-8";Connection con = DriverManager.getConnection(url, "root", "1234");//3、獲取語句對象Statement st = con.createStatement();//4、下面為Java實現事務處理try {con.setAutoCommit(false);//從設置false開始,以下都是一個事務String sql = "insert into aa values(1,'張三');";st.execute(sql);//增sql = "delete from aa where id = 5";st.execute(sql);//刪sql = "update aa set sname='rose111' where id=6";st.execute(sql);con.commit();//提交} catch (Exception e) {con.rollback();//如果出現異常,我們就讓事務回滾} finally{con.setAutoCommit(true);//再設置回去con.close();}}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
事務隔離級別(加鎖):
SQL標準定義了4類隔離級別,包括了一些具體規則,用來限定事務內外的哪些改變是可見的,哪些是不可見的。低級別的隔離級一般支持更高的并發處理,并擁有更低的系統開銷。
查詢事務隔離級別:
select @@tx_isolation;- 1
- 1
Read Uncommitted(讀取未提交內容)
在該隔離級別,所有事務都可以看到其他未提交事務的執行結果。本隔離級別很少用于實際應用,因為它的性能也不比其他級別好多少。讀取未提交的數據,被稱之為臟讀(Dirty Read)。
測試流程: 1、A設置read-uncommitted, start transaction 設置事務隔離級別(read-uncommitted): set session transaction isolation level read uncommitted; 2、B執行start transaction,再修改一條記錄, 3、A查詢記錄,得到了以為正確的記錄 4、B回滾。 問題:A讀到了B沒有提交的記錄,也就是臟讀。- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
Read Committed(讀取提交內容)
這是大多數數據庫系統的默認隔離級別(但不是MySQL默認的)。它滿足了隔離的簡單定義:一個事務只能看見已經提交事務所做的改變。
這種隔離級別 也支持所謂的不可重復讀(Nonrepeatable Read),因為同一事務的其他實例在該實例處理其間可能會有新的commit,所以同一select可能返回不同結果。
不可重復讀(nonrepeatable read):?
一個從開始直到提交之前所做的任何修改對其它事務都是不可見的。兩次同樣的查詢可能會得到不一樣的結果。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
Repeatable Read(可重讀)-MySQL的默認事務隔離級別
它確保同一事務的多個實例在并發讀取數據時,會看到同樣的數據行。
保證了在同一事務中多次讀取結果是一致的。但會引起另外一個幻讀問題,當某個事務在讀取某個范圍記錄時,另外一個事務在該范圍插入和新記錄,當之前事務再次讀取該范圍記錄時會產生幻行。
測試流程: 1、A設置repeatable-read, start transaction,查詢記錄,結果是老的記錄 設置事務隔離級別(repeatable-read,MySQL默認): set session transaction isolation level repeatable read; 2、B執行start transaction,修改一條記錄,查詢記錄,記錄已經修改成功 3、A查詢記錄,結果還是老的記錄 4、B提交事務 5、A再次查詢記錄,結果還是老的記錄。 問題:可以重復讀,A在事務過程中,即使B修改了數據,并且commit,A讀取的還是老的數據。即可重復讀。 注意:這里可能會存在一個新的問題,A在事務過程中,B增加一條記錄,并提交,導致A的兩次讀取不一致,會多一條記錄,也就是幻影讀。InnoDB和Falcon存儲引擎通過多版本并發控制(MVCC,Multiversion Concurrency Control)機制解決了該問題。- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
Serializable(可串行化)
這是最高的隔離級別,它通過強制事務排序,使之不可能相互沖突,從而解決幻讀問題。簡言之,它是在每個讀的數據行上加上共享鎖。在這個級別,可能導致大量的超時現象和鎖競爭。
測試流程: 1、A設置serializable, start transaction,查詢記錄,結果是老的記錄 設置事務隔離級別(serializable,最高級別): set session transaction isolation level serializable; 2、B執行start transaction,修改一條記錄,B卡在這里,要等待A完成才行。 3、A查詢記錄,結果還是老的記錄,A提交。 4、B的修改操作才進行下去。 注意:B在等待過程中,會出現lock超時。- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
小知識點:
共享鎖:如果事務T對數據A加上共享鎖后,則其他事務只能對A再加共享鎖,不能加排他鎖。獲準共享鎖的事務只能讀數據,不能修改數據。 排他鎖:如果事務T對數據A加上排他鎖后,則其他事務不能再對A加任任何類型的封鎖。獲準排他鎖的事務既能讀數據,又能修改數據。- 1
- 2
- 1
- 2
查看當前隔離級別:
select @@tx_isolation;- 1
- 1
設置隔離級別語法:
set [session | global] transaction isolation level {read uncommitted | read committed | repeatable read | serializable}- 1
- 1
這四種隔離級別采取不同的鎖類型來實現,若讀取的是同一個數據的話,就容易發生問題。例如:
臟讀(Drity Read):某個事務已更新一份數據,另一個事務在此時讀取了同一份數據,由于某些原因,前一個RollBack(回滾)了操作,則后一個事務所讀取的數據就會是不正確的。
不可重復讀(Non-repeatable read):在一個事務的兩次查詢之中數據不一致,這可能是兩次查詢過程中間插入了一個事務更新的原有的數據。
幻讀(Phantom Read):在一個事務的兩次查詢中數據筆數不一致,例如有一個事務查詢了幾列(Row)數據,而另一個事務卻在此時插入了新的幾列數據,先前的事務在接下來的查詢中,就會發現有幾列數據是它先前所沒有的。
總結
以上是生活随笔為你收集整理的MySQL事务处理与事务隔离(锁机制)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java替换html中的样式
- 下一篇: 《数据库SQL实战》查找入职员工时间排名