1. 程式人生 > >2.數據庫之事務管理

2.數據庫之事務管理

數據庫 並發控制 事務

1.3 並發控制 不論何時,只要有多個連接在同一時刻修改數據,就會產生並發問題。但是當多個連接只做讀取數據操作時,不會產生並發控制的問題,因為讀取操作不會修改數據。 在事務執行過程中,只有執行commit或者rollback後,鎖才會被釋放,而且是該事務內所有表的鎖同步釋放。 1.3.1 讀寫鎖 對於並發問題的解決方案就是並發控制。並發控制是由鎖系統來完成的,鎖系統包含兩種鎖,共享鎖和排他鎖,也叫讀鎖和寫鎖。讀鎖是共享的,相互不堵塞,也就是說在同一時刻多個連接可以讀取同一資源而不相互幹擾。寫鎖是拍他的,也就是說一個寫鎖會阻塞其他的讀鎖和寫鎖。 1.3.2 鎖粒度 提高共享資源並發性的方式就是讓鎖定對象更有選擇性。盡量只鎖定需要修改的部分而不是所有數據。這樣不會影響到其他線程對未鎖定數據的讀取和寫操作。 問題是加鎖也需要消耗資源。包括鎖的各項操作,比如加鎖、釋放鎖、檢查鎖是否解除,都會加大系統的開銷。如果花費部分性能去管理鎖而不是讀取數據,也會影響到系統的性能。這就涉及到鎖策略。所謂的鎖策略就是在系統性能和數據安全性之間尋求平衡。mysql的每種存儲引擎都有自己的鎖策略。 最重要的兩種鎖策略:表鎖和行級鎖。 表鎖:表鎖會鎖定整張表,是對系統開銷最小的鎖策略。當一個線程對表進行寫操作時,整張表被鎖定,這會阻塞其他的線程對該表的讀寫操作。盡管存儲引擎層可以管理鎖,mysql服務層也會使用有效的表鎖實現不同的目的。例如服務器層會為諸如alter table之類加表鎖,忽略存儲引擎層的鎖機制。 行級鎖:行級鎖可以最大程度的支持並發處理(同時也帶來了最大的鎖開銷)。行級鎖只在存儲引擎層實現。 在實際的數據庫系統中,每時每刻都在發生鎖定,當某個用戶正在修改某一部分數據時,mysql會通過鎖定防止其他用戶讀取同一數據。 1.4 事務 1.4.1 事務的特性:原子性、隔離性、持久性 原子性:整個事務中的所有操作要麽全部成功,要麽全部失敗,對於一個事務來說,不可能只執行其中的一部分。 隔離性:一個事務所做的修改在提交之前,其他的事務是不可見的。 持久性:一旦事務提交,所做的修改就會永久保存到數據庫中。 1.4.2 事務的隔離級別: 1. 讀未提交:一個事務可以讀取另一個事務未提交的數據。這樣會產生臟讀,實際生產環境一般不會用。 2. 讀提交/(另一個事務執行update操作時本事務不可重復讀):一個事務A有兩個相同的sql查詢語句,這個事務開啟第一個查詢語句時,另一個事務B開始對這條數據執行更新(update)操作,那麽事務B會對這條記錄開啟行級鎖,此時事務A就會被阻塞,第二條查詢的sql語句要在事務B執行完後才能執行,而此時事務A的第二次查詢結果跟第一次查詢結果就不一樣了。這就是不可重復讀。讀提交可以解決臟讀的問題。大部分的數據庫默認采用讀提交的事務隔離級別,但mysql不是。 3. 可重復讀(解決了不可重復讀的問題,但是在另一個事務執行insert操作時,會出現幻讀):事務A開始讀取數據時,其他的事務不允許進行修改(update)操作。mysql默認采用重復讀的隔離級別。但是重復讀可能會出現幻讀,因為重復讀針對的是update操作。如果事務A要預覽用戶的消費清單並打印清單,預覽時,用戶有10條消費記錄,而在打印清單之前,用戶又消費了一筆,事務B執行了添加操作並提交了事務,此時事務A打印的清單會發現多了一條記錄,這就是幻讀。 4. 串行執行事務。 mysql默認的事務隔離級別是可重復讀,當然可以修改mysql默認的事務隔離級別。 1.4.3 死鎖 死鎖是指兩個或多個事務已經鎖定了某個資源,並互相請求去鎖定對方已經鎖定的資源,這樣會造成多個事務無法釋放鎖導致惡性循環。這樣每個事務都不會執行完並一直占有鎖。 例如: 事務1: start transaction; update student set name = ‘zhangsan‘ where id = 1; update student set name = ‘lisi‘ where id = 2; commit; 事務2: start transaction; update student set name = ‘zhangsan‘ where id = 2; update student set name = ‘lisi‘ where id = 1; commit; 如果湊巧,兩個事務都執行了第一條sql,更新了一條數據,也就是鎖定了改行數據。接著每個事務都嘗試執行第二條sql,卻發現該行已被對方鎖定。然後兩個事務都等待對方釋放鎖,同時又擁有對方需要的鎖,陷入死循環。除非有外部因素介入才能解除死鎖。 1.4.4 mysql中的事務 mysql的事務默認采用autocommit模式。也就是說只要不顯式的開啟一個事務,每一條sql都會被當做當做一個事務執行提交操作。在當前jdbc連接中,可以通過設置autocommit變量來啟用或禁用自動提交模式。 1.4.5 在事務中混合使用存儲引擎 mysql服務器層不管理事務,事務由下層的存儲引擎實現。所以在同一個事務中,使用多種存儲引擎是不可靠的。 如果在事務中操作了事務型的表和非事務型的表,在正常提交事務時不會出現問題。但是如果事務回滾,事務型的表數據會回滾,而非事務型的表則不會回滾,因為非事務型的表不支持事務,這樣就會導致數據紊亂。所以,為每張表選擇合適的存儲引擎非常重要。 mysql是自動提交事務的,使用jdbc時,只要不顯式的關閉自動提交,每一條sql都是一個事務。所以最好去創建一個事務,把下面的

所有操作放到一個事務裏,要不都成功,要不都失敗。

2.數據庫之事務管理