1. 程式人生 > >數據庫 之 事務控制和隔離級別

數據庫 之 事務控制和隔離級別

可能 處理 eas 獨立 ble space 銷毀 實現 rac

1 概述

事務是指一組原子性的SQL查詢、或者是一個或多個SQL語句組成的獨立工作單元;MyISAM不流行的原因很大是因為其不支持事務的處理功能。

2 事務日誌

事務日誌定義屬性,有些參數可以運行時修改,寫入在配置段裏,事務日誌相當於是中間的輔助功能,而且很關鍵。

事務日誌表示把操作過程一筆一筆記錄下來。如某個線程要對某個行操作,數據庫會先保留老版本於事務日誌中,對文件的寫入,新版本的內容是先寫入到日誌裏,提交前,數據在日誌文件中,而不是在數據文件中,提交操作執行後,才將新舊版本的日誌清除。

執行事務時,每個操作都需要從內存讀入到日誌中

事務日誌主要是為了加速操作,同時為了輔助提交數據的功能,將隨機寫操作轉換為順序寫操作

事務日誌必須是固定大小,一般是有兩個空間,一旦一個空間滿了,就寫入磁盤,另一個空間開始寫入。輪替工作。

為了避免事務日誌所在的磁盤,因硬盤故障導致破壞,可以用raid或者鏡像組同步寫入兩份文件,保證了冗余,實現數據安全

以下是配置文件裏事務日誌的相關參數:

innodb_log_files_in_group:表示一組內有幾個文件,一般要有兩個

innodb_log_group_home_dir:指明家目錄

innodb_log_file_size:指定日誌文件的大小,默認5M

innodb_mirrored_log_groups:日誌組有幾個

3 ACID測試

如果一個存儲引擎支持事務,那麽關系型數據庫就必須滿足ACID測試:而非關系型數據庫是base(堿性的單詞)

A:AUTOMICITY,原子性;整個事務中的所有操作要麽全部成功執行,要麽全部失敗後回滾到開始處;

C:CONSISTENCY,一致性;數據庫總是應該從一個一致性狀態轉為另一個一致性狀態;

I:ISOLATION,隔離性;一個事務所做出的操作在提交之前,是否能為其它事務可見;出於保證並發操作之目的,隔離有多種級別; 隔離如果做得嚴格,可能導致串行執行,而失去了並發執行的意義。有四個級別,隔離性最低,並發性最高,隔離性最高,安全性也最高,但是並發性就最低。可以根據安全性和服務器的並發性選擇一個合適的方案。

D:DURABILITY,持久性;事務一旦提交,其所做出的修改會永久保存;

4 事務控制

自動提交:單語句事務,影響性能

mysql> SELECT @@autocommit;#查看自動提交功能參數

mysql> SET @@session.autocommit=0;#關閉自動提交功能後需要手動控制事務

手動控制事務,事務一旦提交,就不能回滾:

啟動事務:START TRANSACTION

提交事務:COMMIT

回滾事務:ROLLBACK

事務支持savepoints:保存點,相當於是虛擬機的快照

SAVEPOINT identifier#創建保存點

ROLLBACK [WORK] TO [SAVEPOINT] identifier #還原到某個保存點

RELEASE SAVEPOINT identifier#銷毀savepoint

例子

MariaDB [sunny]> insert into classlist values ("su",10,"91"),("chen",18,"88");MariaDB [sunny]>

#創建保存點first

MariaDB [sunny]> savepoint first;

MariaDB [sunny]> update classlist set name=ghbsunny where nu=1;

#創建保存點second

MariaDB [sunny]> saveponit second;

如果不修改nu=1的name值,此時執行

MariaDB [sunny]> rollback to first;

#註意,執行完 rollback to first保存點second就不存在了,因為在保存點first的時候,second還沒創建。一旦執行了commint後,就不能rollback

#銷毀保存點first

MariaDB [sunny]> release savepoint first;

5 事務隔離級別

級別由低而高,最高級別是串行化。隔離性越來越好,但是並發性降低。低級別的事務一定有高級別的問題

mysql數據庫默認是第三隔離級別REPEATABLE-READ,其他數據庫一般默認第二級別READ-COMMITTED,所以mysql建議也修改為第二級別的READ-COMMITTED

查看當前會話級定義的事務隔離級別

MariaDB [sunny]> select @@session.tx_isolation;

mysql有四個隔離級別,如下:

READ-UNCOMMITTED:

讀未提交 --> 容易導致臟讀,不被確認的結果也可能被讀取;即沒有提交的情況下,別人也可以看到未提交的更新的記錄

例子:打開兩個crt窗口,登錄mysql,分別關閉自動提交功能和設置隔離級別為READ-UNCOMMITTED

MariaDB [sunny]> SET @@session.autocommit=0;

MariaDB [sunny]> set @@session.tx_isolation="READ-UNCOMMITTED";

MariaDB [sunny]> start transaction;

在窗口1上執行

MariaDB [sunny]> update classlist set name="bf" where nu=10;

此時,窗口1沒有執行commit,但是在窗口2上能夠看到已經更新後的數據,即窗口2上執行如下語句,看到nu=10的name已經更改為bf了,即窗口2可以隨時看到窗口1的任何修改

MariaDB [sunny]> select * from classlist where nu=10;

+------+----+-------+

| name | nu | score |

+------+----+-------+

| bf | 10 | 91.00 |

+------+----+-------+

READ-COMMITTED:

讀提交--> 讀別人確認的數據,可能導致不可重復讀的問題,可能多次讀的結果不一樣;

例子:打開兩個crt窗口,登錄mysql,分別關閉自動提交功能和設置隔離級別為READ-COMMITTED

MariaDB [sunny]> SET @@session.autocommit=0;

MariaDB [sunny]> set @@session.tx_isolation="READ-COMMITTED";

MariaDB [sunny]> start transaction;

在窗口1上執行

MariaDB [sunny]> delete from classlist where nu=1;

此時,窗口1沒有執行commit操作,窗口1上查看到的nu=1已經被刪除,但是查看2還是可以看到nu=1的記錄

窗口2上執行如下

MariaDB [sunny]> select * from classlist where nu=1;

+-------+----+--------+

| name | nu | score |

+-------+----+--------+

| sunny | 1 | 100.00 |

+-------+----+--------+

1 row in set (0.00 sec)

窗口1上執行commit後,窗口2頁查看不到記錄

REPEATABLE-READ:

可重復讀,mysql數據庫默認的隔離級別 --> 導致幻讀的問題,如別的事務已經修改過數據,但是看到的還是舊數據;

例子:打開兩個crt窗口,登錄mysql,分別關閉自動提交功能和設置隔離級別為READ-COMMITTED

MariaDB [sunny]> SET @@session.autocommit=0;

MariaDB [sunny]> set @@session.tx_isolation="REPEATABLE-READ";

MariaDB [sunny]> start transaction;

在窗口1上執行

MariaDB [sunny]> insert into classlist values ("mei",5,99);

此時還沒commit,在窗口1上可以看到新增的數據,但是窗口2上看不到新增加的數據

在窗口1上執行

MariaDB [sunny]> commit;

此時,窗口1上任然可以看到新增加的數據,但是窗口2上看不到新增的nu=5的數據,

窗口2以為沒有nu=5的數據,但是窗口2要插入nu=5的數據,會出現報錯重復數據的提示

MariaDB [sunny]> insert into classlist values ("mei2",5,98);

ERROR 1062 (23000): Duplicate entry '5' for key 'PRIMARY'

MariaDB [sunny]> select * from classlist;

+----------+----+-------+

| name | nu | score |

+----------+----+-------+

| sunny | 1 | 98.00 |

| chao | 3 | 98.00 |

| tracy su | 6 | 95.00 |

+----------+----+-------+

如果要看到新增的數據,窗口2可以退出sql窗口,重新登錄,就可以看到新增nu=5的數據

SERIALIZABLE:

串行化,隔離度最高;只有對方的事務結束(要麽commit,要麽rollback),另一窗口才能執行對同一表格的操作

例子:打開兩個crt窗口,登錄mysql,分別關閉自動提交功能和設置隔離級別為READ-COMMITTED

MariaDB [sunny]> SET @@session.autocommit=0;

MariaDB [sunny]> set @@session.tx_isolation="SERIALIZABLE";

MariaDB [sunny]> start transaction;

在窗口1上執行如下語句,但是不執行commit;自己操作後,沒有確認,則別人也不能查看該表,因為已經該表瑣死。只能在自己提交會回滾後,別人才能查詢到結果。

delete from classlist where nu=8;

此時在窗口2上執行如下語句,那麽窗口2的查詢結果就出不來,等待時間超時後,就會出現報錯

MariaDB [sunny]> select * from classlist;

ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction


數據庫 之 事務控制和隔離級別