1. 程式人生 > 實用技巧 >mysql的事務隔離級別舉例

mysql的事務隔離級別舉例

  事務是怎麼回事,之前已經聊過(參見Oracle事務的隔離 ),無關哪個資料庫,只要提到事務,都是這四種隔離級別。mysql的預設隔離級別是3——可重複讀。更重要的是,是否支援事務,跟mysql的儲存引擎相關。登陸mysql,查詢儲存引擎:

mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine             | Support | Comment                                                        | Transactions
| XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES | | MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO | | MEMORY | YES | Hash based, stored in
memory, useful for temporary tables | NO | NO | NO | | BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO | | MyISAM | YES | MyISAM storage engine | NO | NO | NO | | CSV | YES | CSV storage engine | NO | NO | NO | | ARCHIVE | YES | Archive storage engine | NO | NO | NO | | PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO | | FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 9
rows in set (0.00 sec)

  我們看到,這麼多儲存引擎,也就一個InnoDB支援事務。再瞧一下預設的事務隔離級別:

mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)

mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

  我們看到,不管是當前會話也好,整個系統也好,預設的隔離級別都是可重複讀。

  再看下預設的事務自動提交開關:

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)

  我們把上面的開關給關了,好測試:

mysql> set autocommit=off;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+
1 row in set, 1 warning (0.00 sec)

  我們建個表測試一下:

mysql> create table test_wlf
    -> (
    -> id INT(11),
    -> name VARCHAR(25)
    -> );
Query OK, 0 rows affected (0.06 sec)

  插入一條資料:

mysql> insert into test_wlf values(1,"wulf");
Query OK, 1 row affected (0.03 sec)

mysql> select * from test_wlf;
+------+------+
| id   | name |
+------+------+
|    1 | wulf |
+------+------+
1 row in set (0.00 sec)

  再來一個視窗,同樣把autocommit關掉,兩事務同時搞起:

  因為當前的事務隔離級別是可重複讀,所以右邊的事務始終可以重複讀取到wulf這條資料,即使左邊的事務新增了wumanshu這條資料,按理應該出現幻讀,可惜已經被InnoDB用mvcc(多版本併發控制)解決了。換句話說,幻讀在InnoDB已經死絕了。

  接下來我們把兩個視窗都改成已提交讀

mysql> set tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)
mysql> set global tx_isolation='READ-COMMITTED';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-COMMITTED        |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

  再試試修改資料:

  以上可以看到已提交讀出現了不可重複讀。繼續,接下來我們把兩個視窗都改成未提交讀

mysql> set tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> set global tx_isolation='READ-UNCOMMITTED';
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED      |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

  再次更新id為2的name值,事務的中間結果都被查出來了,髒讀出現: