當前在開發ERP系統,使用到的數據庫為Mysql。下面介紹下如何開啟事務,以及事務隔離的機制 :
1. 檢查當前數據庫使用的存儲引擎。
show engines;
2. 修改前my.ini中的文件如下:
3. 修改my.ini的文件如下。
3.1 修改了默認的存儲引擎
3.2 增加了mysql數據庫的事務隔離級別, 如果不添加默認是REPEATABLE-READ.
4. 只需要重啟mysql的服務即可。
net stop mysql
net start mysql
5. 再次查詢show engines,顯示如下
6. 事務隔離機制的說明,以下引用自別人的文章
- 未提交讀(READ UNCOMMITTED)。另一個事務修改了數據,但尚未提交,而本事務中的SELECT會讀到這些未被提交的數據(臟讀)。
- 提交讀(READ COMMITTED)。本事務讀取到的是最新的數據(其他事務提交后的)。問題是,在同一個事務里,前后兩次相同的SELECT會讀到不同的結果(不重復讀)。如兩個會話a和b,由於是read committed所以只有當事務提交后才能被別的事務可見,當a執行查詢后b執行插入,b執行commit提交事務,這時a再次查詢結果確實不一樣的,a的兩次查詢同屬於一個事務,即為不可重復讀。
- 可重復讀(REPEATABLE READ)。在同一個事務里,SELECT的結果是事務開始時時間點的狀態,因此,同樣的SELECT操作讀到的結果會是一致的。直到提交事務后再查詢才可以看到其他事務在本事務執行期間鎖進行的更改操作。在MySQL中InnoDB和XtraDB存儲引擎通過多版本並發控制(MVCC)解決了幻讀的問題。
- 串行化(SERIALIZABLE)。讀操作會隱式獲取共享鎖,可以保證不同事務間的互斥。
-
SQL 事務隔離級別
在MySQL中默認事務隔離級別是可重復讀(Repeatable read).可通過SQL語句查詢:
查看InnoDB系統級別的事務隔離級別:mysql> SELECT @@global.tx_isolation;
在MySQL中默認事務隔離級別是可重復讀(Repeatable read).可通過SQL語句查詢:
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
mysql> create table test(i int) engine=innodb;
mysql> insert into test values(1);
Query OK, 1 row affected (0.00 sec)
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
查看InnoDB系統級別的事務隔離級別:
mysql> SELECT @@global.tx_isolation;
結果:
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
查看InnoDB會話級別的事務隔離級別:
mysql> SELECT @@tx_isolation;
結果:
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
修改事務隔離級別:
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
InnoDB 的可重復讀隔離級別和其他數據庫的可重復讀是有區別的,不會造成幻象讀(phantom read),所謂幻象讀,就是同一個事務內,多次select,可以讀取到其他session insert並已經commit的數據。下面是一個小的測試,證明InnoDB的可重復讀隔離級別不會造成幻象讀。測試涉及兩個session,分別為 session 1和session 2,隔離級別都是repeateable read,關閉autocommit
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set (0.00 sec)
mysql> set autocommit=off;
Query OK, 0 rows affected (0.00 sec)
session 1 創建表並插入測試數據
mysql> create table test(i int) engine=innodb;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(1);
Query OK, 1 row affected (0.00 sec)
session 2 查詢,沒有數據,正常,session1沒有提交,不允許臟讀
mysql> select * from test;
Empty set (0.00 sec)
mysql> select * from test;
Empty set (0.00 sec)
session 1 提交事務
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
session 2 查詢,還是沒有數據,沒有產生幻象讀
mysql> select * from test;
Empty set (0.00 sec)
當session2提交事務后才可以看到session1的插入數據;
以上試驗版本:
mysql> select version();
+-------------------------+
| version() |
+-------------------------+
| 5.0.37-community-nt-log |
+-------------------------+
1 row in set (0.00 sec)
mysql> select * from test;
Empty set (0.00 sec)
當session2提交事務后才可以看到session1的插入數據;
以上試驗版本:
mysql> select version();
+-------------------------+
| version() |
+-------------------------+
| 5.0.37-community-nt-log |
+-------------------------+
1 row in set (0.00 sec)