mysql的事務隔離級別舉例
阿新 • • 發佈:2020-12-04
事務是怎麼回事,之前已經聊過(參見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 inmemory, 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 | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ 9rows 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值,事務的中間結果都被查出來了,髒讀出現: