如何查看mysql事务的隔离级别是多少 mysql查看隔离级别出错_mysql


文章目录

  • 事务隔离级别
  • 执行 SQL 语句,查看数据库的事务隔离级别
  • 修改配置文件,改变数据库的事务隔离级别(永久)
  • 执行 SQL 语句,修改数据库的事务隔离级别(临时)
  • 读未提交 read uncommitted
  • 读已提交 read committed
  • 可重复读 repeatable read
  • 串行化 serializable


事务隔离级别

执行 SQL 语句,查看数据库的事务隔离级别

mysql> show variables like 'transaction_isolation';

修改配置文件,改变数据库的事务隔离级别(永久)

[mysqld]
...
# transaction-isolation=READ-UNCOMMITTED
# transaction-isolation=READ-COMMITTED
# transaction-isolation=REPEATABLE-READ
# transaction-isolation=SERIALIZABLE

默认是 REPEATABLE-READ 。修改配置文件后记得要重启 MySQL Server 。

执行 SQL 语句,修改数据库的事务隔离级别(临时)

-- SQL命令:对当前会话生效。会话断开、重连后失效。
set session transaction isolation level read uncommitted;
set session transaction isolation level read committed;
set session transaction isolation level repeatable read;
set session transaction isolation level serializable;

-- SQL命令:对后续会话生效。MySQL Server 重启后失效。
set global transaction isolation level read uncommitted;
set global transaction isolation level read committed;
set global transaction isolation level repeatable read;
set global transaction isolation level serializable;

验证时注意两点:

  1. 记得关闭自动提交功能:mysql> set autocommit = off;
  2. 最好使用命令行黑窗口进行验证。因为有些图形化工具会复用 session ,导致你看不到预期效果。

读未提交 read uncommitted

读未提交隔离级别意味着我(当前事务)在事务执行期间,能看到别人(另一个事务)还未提交的数据。

验证(A 事务是「别人」,正常执行,无需考虑其它;B 事务是「我」,会受 A 事务的影响):

  1. A 事务和 B 事务分别开始(mysql> begin;);
  2. A 事务执行 update 语句。此时,A 事务未提交(commit);
  3. B 事务执行 select 语句,你会发现 B 事务查到的是 A 事务修改的但未提交的数据。

「我读到了别人未提交的数据」这种现象也被称为脏读。读未提交隔离级别在生产环境中不具有使用价值。

读已提交 read committed

读已提交隔离级别解决了读未提交级别的问题。

读一今提交隔离级别意味着我(当前事务)在事务执行期间,只能看到别人(另一个事务)已经提交的数据,它改动了的但未提交的数据对我而言不可见。

验证(A 事务是「别人」,正常执行,无需考虑其它;B 事务是「我」,会受 A 事务的影响):

  1. A 事务和 B 事务分别开始(mysql> begin;);
  2. A 事务执行 update 语句。此时,A 事务未提交(commit);
  3. B 事务执行 select 语句,你会发现 B 事务查到的还是老数据,即 A 事务改动前的数据;
  4. A 事务提交后,B 事务再次执行 select 语句,此时你会发现 B 事务现在查到的才是 A 事务改动后的数据。

读已提交 read commited 时很多数据库的默认事务隔离级别,例如 Oracle 和 PostgreSQL 。

可重复读 repeatable read

前一个隔离级别有一个问题(当然,有些人认为这不是个问题,只能算是个现象):在 B 事务执行期间,因为 A 事务的提交,导致 B 事务在 A 事务提交前后执行同样的 select 语句会看到不同的数据内容。

站在「上帝视角」你会觉得这很正常,如果单站在 B 的视角就有点怪怪的感觉:我明明没有动这个数据,它怎么突然就变了?

可重复读隔离级别解决了这个问题:我(当前事务)在事务执行期间,当我 select 一个数据之后,无论别人(另一个事务)有没有改动这个数据,我再次 select 这个数据仍然会看到我第一次看到的那个样子。

验证(A 事务是「别人」,正常执行,无需考虑其它;B 事务是「我」,会受 A 事务的影响):

  1. A 事务和 B 事务分别开始(mysql> begin;);
  2. B 事务执行 select 语句,查询某条数据;
  3. A 事务执行 update 语句并提交,改动同一条数据;
  4. B 事务再次执行同样的 select 语句,查询之前查询过的数据,会看到仍然是改动前的数据;
  5. B 事务提交;
  6. 这时 B 再查询,才会看到 A 改动后的数据(之前不会)。

可重复读 repeatable read 是 MySQL 的默认隔离级别。其实,MySQL 之所以默认隔离级别要高一些是因为 MySQL 的实现缺陷导致在某些极端情况下使用读已提交 read committed 会出问题,所以,MySQL 迫于无奈才只能提升默认隔离级别等级。

串行化 serializable

串行化 serializable 是最高级别的隔离级别。这种级别下,一个事务中的 SQL 语句的执行会因为另一个事务而阻塞等待。

验证(A 事务是「别人」,正常执行,无需考虑其它;B 事务是「我」,会受 A 事务的影响):

  1. A 事务和 B 事务分别开始(mysql> begin;);
  2. A 事务执行 update 语句,此时未提交;
  3. B 事务执行 select 语句,你会发现有类似「卡死、无反应」的现象,实际上是 B 事务的 select 语句在等待;
  4. A 事务执行提交;
  5. 这个时候,B 事务之前执行的 select 语句的查询结果才出来。