1. 程式人生 > 其它 >python:考試練手習題

python:考試練手習題

  事務是由一組SQL語句組成的邏輯處理單元,具有4個屬性,通常簡稱為事務的ACID屬性。

A (Atomicity) 原子性:整個事務中的所有操作,要麼全部完成,要麼全部不完成,不可能停滯在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。使用 undo log ,從而達到回滾 C (Consistency) 一致性:在事務開始之前和事務結束以後,資料庫的完整性約束沒有被破壞。使用 redo log,從而達到故障後恢復 I (Isolation)隔離性:一個事務的執行不能其它事務干擾。即一個事務內部的操作及使用的資料對其它併發事務是隔離的,併發執行的各個事務之間不能互相干擾。使用鎖以及MVCC,運用的優化思想有讀寫分離,讀讀並行,讀寫並行 D (Durability) 永續性:在事務完成以後,該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被回滾。通過回滾,以及恢復,和在併發環境下的隔離做到一致性。

  沒有事務隔離,可能會匯入如下問題:

  • 更新丟失(Lost Update):事務A和事務B選擇同一行,然後基於最初選定的值更新該行時,由於兩個事務都不知道彼此的存在,就會發生丟失更新問題
  • 髒讀(Dirty Reads):事務A讀取了事務B更新的資料,然後B回滾操作,那麼A讀取到的資料是髒資料
  • 不可重複讀(Non-Repeatable Reads):事務 A 多次讀取同一資料,事務B在事務A多次讀取的過程中,對資料作了更新並提交,導致事務A多次讀取同一資料時,結果不一致。
  • 幻讀(Phantom Reads):幻讀與不可重複讀類似。它發生在一個事務A讀取了幾行資料,接著另一個併發事務B插入了一些資料時。在隨後的查詢中,事務A就會發現多了一些原本不存在的記錄,就好像發生了幻覺一樣,所以稱為幻讀。 

  事務隔離級別

  SQL-92標準中定義的四種隔離級別。在MySQL中,預設的隔離級別是REPEATABLE-READ(可重複讀),並且解決了幻讀問題(利用Gap Locks和Next-key可以阻止其他事務在鎖定區間內插入資料)。不可重複讀重點在於Update和delete,而幻讀的重點在於insert

  • 讀未提交:一個事務可以讀取到另一個事務未提交的修改。這會帶來髒讀,幻讀,不可重複讀問題
  • 讀已提交:一個事務只能讀取另一個事務已經提交的修改。其避免了髒讀,仍然存在不可以重複讀和幻讀問題
  • 可重複讀:同一個事務中多次讀取相同的資料返回的結果是一樣的。其避免了髒讀和不可重複讀問題,但是幻讀依然存在
  • 序列化:事務序列之行。避免了以上所有問題

 【MVCC】

  MVCC (MultiVersion Concurrency Control) 叫做多版本併發控制。InnoDB的 MVCC ,是通過在每行記錄的後面儲存兩個隱藏的列來實現的。這兩個列,一個儲存了行的建立時間,一個儲存了行的過期時間,在實際操作中,儲存的並不是時間,而是事務版本號,每開啟一個新事務,事務的版本號就會遞增。

  增刪改查中對版本號的作用如下:

  • select:讀取建立版本小於或等於當前事務版本號,並且刪除版本為空或大於當前事務版本的記錄。這樣可以保證在讀取之前記錄都是存在的
  • insert:將當前事務的版本號儲存至行的建立版本號
  • update:新插入一行,並以當前事務版本號作為新行的建立版本號,同時將原記錄行的刪除版本號設定為當前事務版本號
  • delete:將當前事務版本號儲存至行的刪除版本號

  快照讀和當前讀:普通的select就是快照讀,而update,delete,insert,select...LOCK In SHARE MODE,SELECT...for update就是當前讀

  • 快照讀:讀取的是快照版本,也就是歷史版本
  • 當前讀:讀取的是最新版版

  存在這的情況,兩個事務,對同一條資料做修改。最後結果應該是哪個事務的結果呢,肯定要是時間靠後的那個,並且更新之前要先讀資料,這裡所說的讀和上面說到的讀不一樣,更新之前的讀叫做“當前讀”,總是當前版本的資料,也就是多版本中最新一次提交的那版。

  假設事務A執行 update 操作, update 的時候要對所修改的行加行鎖,這個行鎖會在提交之後才釋放。而在事務A提交之前,事務B也想 update 這行資料,於是申請行鎖,但是由於已經被事務A佔有,事務B是申請不到的,此時,事務B就會一直處於等待狀態,直到事務A提交,事務B才能繼續執行,如果事務A的時間太長,那麼事務B很有可能出現超時異常。

 【Gap Lock && Next-Key Lock】

  併發寫問題的解決方式就是行鎖,而解決幻讀用的也是鎖,叫做間隙鎖,MySQL 把行鎖和間隙鎖合併在一起,解決了併發寫和幻讀的問題,這個鎖叫做 Next-Key鎖。

redo log 與 undo log

 【redo log】

叫做重做日誌,是用來實現事務的永續性。該日誌檔案由兩部分組成:重做日誌緩衝(redo log buffer,在記憶體中)以及重做日誌檔案(redo log,在磁碟中)。當事務提交之後會把所有修改資訊都會存到該日誌中。

start transaction;
select balance from bank where name="zhangsan";
// 生成 重做日誌 balance=600
update bank set balance = balance - 400; 
// 生成 重做日誌 amount=400
update finance set amount = amount + 400;
commit;

  mysql 為了提升效能不會把每次的修改都實時同步到磁碟,而是會先存到Boffer Pool(緩衝池)裡頭,把這個當作快取來用。然後使用後臺執行緒去做緩衝池和磁碟之間的同步。如果還沒來得及同步的時候宕機或斷電了,這樣會導致丟部分已提交事務的修改資訊!所以引入了redo log來記錄已成功提交事務的修改資訊,並且會把redo log持久化到磁碟,系統重啟之後在讀取redo log恢復最新資料。redo log是用來恢復資料的 用於保障,已提交事務的持久化特性.

  undo log】

  叫做回滾日誌,用於記錄資料被修改前的資訊。他正好跟前面所說的重做日誌所記錄的相反,重做日誌記錄資料被修改後的資訊。undo log主要記錄的是資料的邏輯變化,為了在發生錯誤時回滾之前的操作,需要將之前的操作都記錄下來,然後在發生錯誤時才可以回滾。

  每次寫入資料或者修改資料之前都會把修改前的資訊記錄到 undo log。undo log 記錄事務修改之前版本的資料資訊,因此假如由於系統錯誤或者rollback操作而回滾的話可以根據undo log的資訊來進行回滾到沒被修改前的狀態。undo log是用來回滾資料的用於保障 未提交事務的原子性