事务是MySQL的Innodb存储引擎比较大的亮点,大家对事务的隔离级别肯定都不陌生,那么如何查看当前事务的隔离级别呢?这个方法可能大家也知道,不就是查看当前的transaction_isolation变量么?下面我们分三个部分给说说这个修改隔离级别的操作:
1、修改全局隔离级别(set global trx_isolation)
操作如下:
session 1
##查看全局隔离级别
mysql yeyztest 21:28:09>>select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-COMMITTED |
+-----------------------+
1 row in set (0.00 sec)
##查看当前回话的隔离级别
mysql yeyztest 21:28:42>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-COMMITTED |
+------------------------+
1 row in set (0.00 sec)
mysql yeyztest 21:28:50>>select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set (0.00 sec)
此时我们在另外一个session 2上面修改全局的隔离级别,然后再在回话1上面查看隔离级别。步骤如下:
SESSION 2:
##修改全局隔离级别
mysql yeyztest 21:37:07>>set global transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
然后我们再看session 1的结果,如下:
mysql yeyztest 21:30:16>>select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
mysql yeyztest 21:37:42>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-COMMITTED |
+------------------------+
1 row in set (0.00 sec)
说明修改了全局隔离级别并不会影响当前回话session 1的隔离级别,当我们退出当前回话,再次进入的时候,可以发现,当前session 1的隔离级别也变成了RR,如下:
session 1:
mysql (none) 21:43:44>>select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ |
+-----------------------+
1 row in set (0.00 sec)
mysql (none) 21:43:46>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ |
+------------------------+
1 row in set (0.00 sec)
2、修改当前回话的隔离级别(set session tx_isolation)
在这种情况下,我们在session 1上面使用set session transaction isolation的方法改变session 1的隔离级别,如下:
mysql 21:43:46>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| REPEATABLE-READ |
+------------------------+
1 row in set (0.00 sec)
mysql 21:48:43>>set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
mysql 21:49:21>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED |
+------------------------+
1 row in set (0.00 sec)
可见当我们使用set session 的方法改变隔离级别的时候,直接会生效。
3、修改下一个事务的隔离级别(set trx_isolation)
再来看第三种情况,在上述修改隔离级别的基础上,我们不加session关键字,看看有什么区别:
mysql--dba_admin@127.0.0.1:(none) 21:51:35>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED |
+------------------------+
1 row in set (0.00 sec)
mysql--dba_admin@127.0.0.1:(none) 21:51:47>>set transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
mysql--dba_admin@127.0.0.1:(none) 21:52:00>>select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED |
+------------------------+
1 row in set (0.00 sec)
我们使用不含session和global的语句将隔离级别改成了read committed,再次查看,看到的结果是read-uncommitted,貌似是没有修改成功,但是别着急,接着做一个试验,我们在session 1上开启一个事务,然后在session 2上查看当前的隔离级别:
session 1:
mysql 21:53:27>>begin;
Query OK, 0 rows affected (0.00 sec)
mysql 21:55:10>>select * from yeyztest.slowquery_custom where id=1 for update;
Empty set (0.00 sec)
session 2:
这里需要注意,session 2上我们如何查询当前session 1中事务的隔离级别呢?可以使用information_schema,这个数据库里面有一个innodb_trx表,这个表的内容就是当前执行的事务的隔离级别:
mysql 21:55:46>>select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 1178769
trx_state: RUNNING
trx_started: 2019-05-18 21:55:39
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 1
trx_mysql_thread_id: 3336333
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 1
trx_lock_structs: 1
trx_lock_memory_bytes: 1136
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: READ COMMITTED
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec)
看到了么,这里的值变成了READ COMMITTED,就是说,session 1里面的事务的隔离级别是READ COMMITTED,也就是说,上一步中我们使用set transation isolation语法设置的隔离级别起作用了。
此时我们在session 1上面进行commit操作,然后重新开启一个事务,如下:
session 1:
mysql 22:04:37>>commit;
Query OK, 0 rows affected (0.00 sec)
mysql 22:08:40>>begin;
Query OK, 0 rows affected (0.00 sec)
mysql 22:08:43>>select * from yeyztest.slowquery_custom where id=1 for update;
Empty set (0.00 sec)
mysql 22:08:46>>
再来看session 2,如下:
mysql 21:55:48>>select * from information_schema.innodb_trx\G
*************************** 1. row ***************************
trx_id: 1178848
trx_state: RUNNING
trx_started: 2019-05-18 22:08:46
trx_requested_lock_id: NULL
trx_wait_started: NULL
trx_weight: 1
trx_mysql_thread_id: 3336333
trx_query: NULL
trx_operation_state: NULL
trx_tables_in_use: 0
trx_tables_locked: 1
trx_lock_structs: 1
trx_lock_memory_bytes: 1136
trx_rows_locked: 0
trx_rows_modified: 0
trx_concurrency_tickets: 0
trx_isolation_level: READ UNCOMMITTED
trx_unique_checks: 1
trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
trx_adaptive_hash_latched: 0
trx_adaptive_hash_timeout: 0
trx_is_read_only: 0
trx_autocommit_non_locking: 0
1 row in set (0.00 sec)
隔离级别又重新变回了READ UNCOMMITTED,也就是说,使用set transaction isolation的方法,会在下一个事务中生效,而提交了这个事务之后,又会变回原来的隔离级别。
上面的过程,看着比较笼统,简单梳理一下就是:
1、使用set global的方法可以修改全局的隔离级别,修改之后就立即生效;
2、使用set session的方法可以修改当前回话的隔离级别,修改之后立即生效;
3、使用set trx_isolation的方法,不加session和global参数,用来修改下一个事务的隔离级别,当下一个事务提交之后,隔离级别又会变成原来的样子。
4、我们可以通过查询information_schema.innodb_trx表中的记录来查看当前的隔离级别是什么。