确定当前事务的隔离级别

Posted DBA随笔

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了确定当前事务的隔离级别相关的知识,希望对你有一定的参考价值。

18

May,2019

    今天周六,在家休息了一天,下午出去走了走,恰好雨过天晴,在清河边上吹了吹风,感觉蛮不错,看来人还是要多跟大自然接触,上班的时候总是一天到晚坐着,不是一个好现象,以后有钱了还是找个轻松的工作,哈哈哈。


确定当前事务的隔离级别
确定当前事务的隔离级别
确定当前事务的隔离级别


事务的隔离级别

    事务是mysql的Innodb存储引擎比较大的亮点,大家对事务的隔离级别肯定都不陌生,那么如何查看当前事务的隔离级别呢?这个方法可能大家也知道,不就是查看当前的transaction_isolation变量么?下面我们分三个部分给说说这个修改隔离级别的操作:

1、修改全局隔离级别(set global trx_isolation)

操作如下:

session 1

 1##查看全局隔离级别
2mysql yeyztest 21:28:09>>select @@global.tx_isolation;
3+-----------------------+
4| @@global.tx_isolation |
5+-----------------------+
6| READ-COMMITTED        |
7+-----------------------+
81 row in set (0.00 sec)
9
10##查看当前回话的隔离级别
11mysql yeyztest 21:28:42>>select @@session.tx_isolation;
12+------------------------+
13| @@session.tx_isolation |
14+------------------------+
15| READ-COMMITTED         |
16+------------------------+
171 row in set (0.00 sec)
18
19mysql yeyztest 21:28:50>>select @@tx_isolation;
20+----------------+
21| @@tx_isolation |
22+----------------+
23| READ-COMMITTED |
24+----------------+
251 row in set (0.00 sec)

    此时我们在另外一个session 2上面修改全局的隔离级别,然后再在回话1上面查看隔离级别。步骤如下:

SESSION 2:

1##修改全局隔离级别
2mysql yeyztest 21:37:07>>set global transaction isolation level repeatable read;
3Query OK, 0 rows affected (0.00 sec)

然后我们再看session 1的结果,如下:

 1mysql yeyztest 21:30:16>>select @@global.tx_isolation;
2+-----------------------+
3| @@global.tx_isolation |
4+-----------------------+
5| REPEATABLE-READ       |
6+-----------------------+
71 row in set (0.00 sec)
8
9mysql yeyztest 21:37:42>>select @@session.tx_isolation;
10+------------------------+
11| @@session.tx_isolation |
12+------------------------+
13| READ-COMMITTED         |
14+------------------------+
151 row in set (0.00 sec)

    说明修改了全局隔离级别并不会影响当前回话session 1的隔离级别,当我们退出当前回话,再次进入的时候,可以发现,当前session 1的隔离级别也变成了RR,如下:

session 1:

 1mysql (none) 21:43:44>>select @@global.tx_isolation;
2+-----------------------+
3| @@global.tx_isolation |
4+-----------------------+
5| REPEATABLE-READ       |
6+-----------------------+
71 row in set (0.00 sec)
8
9mysql (none21:43:46>>select @@session.tx_isolation;
10+------------------------+
11| @@session.tx_isolation |
12+------------------------+
13| REPEATABLE-READ        |
14+------------------------+
151 row in set (0.00 sec)

2、修改当前回话的隔离级别(set session tx_isolation)

    在这种情况下,我们在session 1上面使用set session transaction isolation的方法改变session 1的隔离级别,如下:

 1mysql  21:43:46>>select @@session.tx_isolation;
2+------------------------+
3| @@session.tx_isolation |
4+------------------------+
5| REPEATABLE-READ        |
6+------------------------+
71 row in set (0.00 sec)
8
9mysql  21:48:43>>set session transaction isolation level read uncommitted;
10Query OK, 0 rows affected (0.00 sec)
11
12mysql  21:49:21>>select @@session.tx_isolation;
13+------------------------+
14| @@session.tx_isolation |
15+------------------------+
16| READ-UNCOMMITTED       |
17+------------------------+
181 row in set (0.00 sec)

    可见当我们使用set session 的方法改变隔离级别的时候,直接会生效。

3、修改下一个事务的隔离级别(set trx_isolation)

   再来看第三种情况,在上述修改隔离级别的基础上,我们不加session关键字,看看有什么区别:

 1mysql--dba_admin@127.0.0.1:(none) 21:51:35>>select @@session.tx_isolation;
2+------------------------+
3| @@session.tx_isolation |
4+------------------------+
5| READ-UNCOMMITTED       |
6+------------------------+
71 row in set (0.00 sec)
8
9mysql--dba_admin@127.0.0.1:(none) 21:51:47>>set  transaction isolation level read committed;
10Query OK, 0 rows affected (0.00 sec)
11
12mysql--dba_admin@127.0.0.1:(none) 21:52:00>>select @@session.tx_isolation;
13+------------------------+
14| @@session.tx_isolation |
15+------------------------+
16READ-UNCOMMITTED       |
17+------------------------+
181 row in set (0.00 sec)

    我们使用不含session和global的语句将隔离级别改成了read committed,再次查看,看到的结果是read-uncommitted,貌似是没有修改成功,但是别着急,接着做一个试验,我们在session 1上开启一个事务,然后在session 2上查看当前的隔离级别:

session 1:

1mysql  21:53:27>>begin;
2Query OK, 0 rows affected (0.00 sec)
3
4mysql  21:55:10>>select * from yeyztest.slowquery_custom where id=1 for update;
5Empty set (0.00 sec)

session 2:

这里需要注意,session 2上我们如何查询当前session 1中事务的隔离级别呢?可以使用information_schema,这个数据库里面有一个innodb_trx表,这个表的内容就是当前执行的事务的隔离级别:

 1mysql  21:55:46>>select * from information_schema.innodb_trxG
2*************************** 1. row ***************************
3                    trx_id: 1178769
4                 trx_state: RUNNING
5               trx_started: 2019-05-18 21:55:39
6     trx_requested_lock_id: NULL
7          trx_wait_started: NULL
8                trx_weight: 1
9       trx_mysql_thread_id: 3336333
10                 trx_query: NULL
11       trx_operation_state: NULL
12         trx_tables_in_use: 0
13         trx_tables_locked: 1
14          trx_lock_structs: 1
15     trx_lock_memory_bytes: 1136
16           trx_rows_locked: 0
17         trx_rows_modified: 0
18   trx_concurrency_tickets: 0
19       trx_isolation_level: READ COMMITTED
20         trx_unique_checks: 1
21    trx_foreign_key_checks: 1
22trx_last_foreign_key_error: NULL
23 trx_adaptive_hash_latched: 0
24 trx_adaptive_hash_timeout: 0
25          trx_is_read_only: 0
26trx_autocommit_non_locking: 0
271 row in set (0.00 sec)

看到了么,这里的值变成了READ COMMITTED,就是说,session 1里面的事务的隔离级别是READ COMMITTED,也就是说,上一步中我们使用set transation isolation语法设置的隔离级别起作用了。

    此时我们在session 1上面进行commit操作,然后重新开启一个事务,如下:

session 1:

 1mysql  22:04:37>>commit;
2Query OK, 0 rows affected (0.00 sec)
3
4mysql  22:08:40>>begin;
5Query OK, 0 rows affected (0.00 sec)
6
7mysql  22:08:43>>select * from yeyztest.slowquery_custom where id=1 for update;
8Empty set (0.00 sec)
9
10mysql  22:08:46>>

再来看session 2,如下:

 1mysql  21:55:48>>select * from information_schema.innodb_trxG
2*************************** 1. row ***************************
3                    trx_id: 1178848
4                 trx_state: RUNNING
5               trx_started: 2019-05-18 22:08:46
6     trx_requested_lock_id: NULL
7          trx_wait_started: NULL
8                trx_weight: 1
9       trx_mysql_thread_id: 3336333
10                 trx_query: NULL
11       trx_operation_state: NULL
12         trx_tables_in_use: 0
13         trx_tables_locked: 1
14          trx_lock_structs: 1
15     trx_lock_memory_bytes: 1136
16           trx_rows_locked: 0
17         trx_rows_modified: 0
18   trx_concurrency_tickets: 0
19       trx_isolation_level: READ UNCOMMITTED
20         trx_unique_checks: 1
21    trx_foreign_key_checks: 1
22trx_last_foreign_key_error: NULL
23 trx_adaptive_hash_latched: 0
24 trx_adaptive_hash_timeout: 0
25          trx_is_read_only: 0
26trx_autocommit_non_locking: 0
271 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表中的记录来查看当前的隔离级别是什么。


确定当前事务的隔离级别





以上是关于确定当前事务的隔离级别的主要内容,如果未能解决你的问题,请参考以下文章

浅析Spring事务传播行为和隔离级别

Spring事务隔离级别:REQUIRES_NEW使用细节

查询修改mysql事务隔离级别

spring事务传播性与隔离级别

如何确认当前事务的隔离级别

Spring的传播行为与隔离级别