【MySQL技术内幕】7.6-事物的隔离级别

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS PostgreSQL,集群系列 2核4GB
简介: 【MySQL技术内幕】7.6-事物的隔离级别

令人惊讶的是,大部分数据库系统都没有提供真正的隔离性,最初或许是因为系统实现者并没有真正理解这些问题。如今这些问题已经弄清楚了,但是数据库实现者在正确性和性能之间做了妥协。ISO和 ANIS SQL标准制定了四种事务隔离级别的标准,但是很少有数据库厂商遵循这些标准。比如 Oracle数据库就不支持READ UNCOMMITTED和 REPEATABLE READ的事务隔离级别。

SQL标准定义的四个隔离级别为:

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

READ UNCOMMITTED称为浏览访问( browse access,仅仅针对事务顶的READ COMMITTED称为游标稳定( cursor stability)。 REPEATABLE READ是2.9999°的隔离,没有幻读的保护。 SERIALIZABLE称为隔离,或3°的隔离。SQL和SQL2标准的默认事务隔离级别是 SERIALIZABLE。

InnoDB存储引擎默认支持的隔离级别是 REPEATABLE READ,但是与标准SQL不同的是, InnoDB存储引擎在 REPEATABLE READ事务隔离级别下,使用Next-Key Lock锁的算法,因此避免幻读的产生。这与其他数据库系统(如 Microsoft SQL Server数据库〕是不同的。所以说, InnoDB存储引擎在默认的 REPEATABLE READ的事务隔离级别下已经能完全保证事务的隔离性要求,即达到SQL标准的 SERIALIZABLE隔离级别。

隔离级别越低,事务请求的锁越少或保持锁的时间就越短。这也是为什么大多数数据库系统默认的事务隔离级别是READ COMMITTED。

据了解,大部分的用户质疑 SERIALIZABLE隔离级别带来的性能问题,但是根据 Jim gray在《 Transaction Processing》一书中指出,两者的开销几乎是一样的,甚至SERIALIZABLE可能更优!因此在 InnoDB存储引擎中选择 REPEATABLE READ的事务隔离级别并不会有任何性能的损失。同样地,即使使用 READ COMMITTED的隔离级别,用户也不会得到性能的大幅度提升。

在 InnoDB存储引擎中,可以使用以下命令来设置当前会话或全局的事务隔离级别:

SET [GLOBAL I SESSION] TRANSACTION ISOLATION LEVEL
{
READ UNCOMMITTED
| READ COMMITTED
| REPEATABLE READ
| SERIALIZABLE
}复制代码

如果想在 MySQL数据库启动时就设置事务的默认隔离级别,那就需要修改MyQL的配置文件,在[mysqld]中添加如下行:

[mysqld]
transaction-isolation=READ-COMMITTED复制代码

查看当前会话的事务隔离级别,可以使用:

mysql> SELECT @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.05 sec)复制代码

查看全局的事务隔离级别,可以使用

mysql> SELECT @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| REPEATABLE-READ       |
+-----------------------+
1 row in set, 1 warning (0.00 sec)复制代码

在SERIALIABLE的事务隔离级别, InnoDB存储引擎会对每个 SELECT语句后自动加上 LOCK IN SHARE MODE,即为每个读取操作加一个共享锁。因此在这个事务隔离级别下,读占用了锁,对一致性的非锁定读不再予以支持。这时,事务隔离级别 SERIALIZABLE符合数据库理论上的要求,即事务是well-formed的,并且是two-phrased的。有兴趣的读者可进一步研究因为 InnoDB存储引擎在 REPEATABLE READ隔离级别下就可以达到3°的隔离,因此一般不在本地事务中使用 SERIALIABLE的隔离级别。 SERIALIABLE的事务隔离级别主要用于 InnoDB存储引擎的分布式事务。

在 READ COMMITTED的事务隔离级别下,除了唯一性的约束检查及外键约束的检查需要 gap lock, InnoDB存储引擎不会使用gap lock的锁算法。但是使用这个事务隔离级别需要注意一些问题。首先,在 MySQL5.1中, READ COMMITTED事务隔离级别默认只能工作在 replication(复制)二进制日志为ROW的格式下。如果二进制日志工作在默认的 STATEMENT下,则会出现如下的错误:

ERROR 1598(HY000): Binary logging not possible. Message: Transaction level 'READ-COMMITTED' in InnoDB is not safe for binlog mode 'STATEMENT复制代码

在 MySQL5.0版本以前,在不支持ROW格式的二进制日志时,也许有人知道通过将参数 innodb_locks_unsafe_for_binlog设置为1可以在二进制日志为 STATEMENT下使用 READ COMMITTED的事务隔离级别:

可以看到,数据产生了不一致。导致这个问题发生的原因有两点:

  • 在READ COMMITTED事务隔离级别下,事务没有使用 gap lock进行锁定,因此用户在会话B中可以在小于等于5的范围内插入一条记录;
  • STATEMENT格式记录的是 master上产生的SQL语句,因此在 master服务器上执行的顺序为先删后插,但是在 STATEMENT格式中记录的却是先插后删,逻辑顺序上产生了不一致。

要避免主从不一致的问题,只需解决上述问题中的一个就能保证数据的同步了。使用 READ REPEATABLE的事务隔离级别可以避免上述第一种情况的发生,也就避免了 master和 slave数据不一致问题的产生。

在 MySQL5.1版本之后,因为支持了ROW格式的二进制日志记录格式,避免了第二种情况的发生,所以可以放心使用READ COMMITTED的事务隔离级别。但即使不使用READ COMMITTED的事务隔离级别,也应该考虑将二进制日志的格式更换成ROW,因为这个格式记录的是行的变更,而不是简单的SQL语句,所以可以避免一些不同步现象的产生,进一步保证数据的同步。InnoDB存储引擎的创始人Heikkituuri也在http://bugs.mysql.com/bug.php?id=33210这个帖子中建议使用ROW格式的二进制日志。



相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
2月前
|
监控 关系型数据库 MySQL
10亿数据如何最快速插入MySQL:技术干货分享
【8月更文挑战第2天】在大数据时代,处理并快速插入数十亿条数据到MySQL数据库是许多企业面临的关键挑战。本文将深入分享一系列高效的技术策略和实战经验,帮助读者优化这一过程,确保数据能够快速、准确地进入数据库系统。
125 1
|
3天前
|
关系型数据库 MySQL 数据库
深入理解MySQL数据库隔离级别
深入理解MySQL数据库隔离级别
15 1
|
17天前
|
存储 关系型数据库 MySQL
技术解析:MySQL中取最新一条重复数据的方法
以上提供的两种方法都可以有效地从MySQL数据库中提取每个类别最新的重复数据。选择哪种方法取决于具体的使用场景和MySQL版本。子查询加分组的方法兼容性更好,适用于所有版本的MySQL;而窗口函数方法代码更简洁,执行效率可能更高,但需要MySQL 8.0及以上版本。在实际应用中,应根据数据量大小、查询性能需求以及MySQL版本等因素综合考虑,选择最合适的实现方案。
86 6
|
2月前
|
人工智能 小程序 关系型数据库
【MySQL】黑悟空都掌握的技能,数据库隔离级别全攻略
本文以热门游戏《黑神话:悟空》为契机,深入浅出地解析了数据库事务的四种隔离级别:读未提交、读已提交、可重复读和串行化。通过具体示例,展示了不同隔离级别下的事务行为差异及可能遇到的问题,如脏读、不可重复读和幻读等。此外,还介绍了在MySQL中设置隔离级别的方法,包括全局和会话级别的调整,并通过实操演示了各隔离级别下的具体效果。本文旨在帮助开发者更好地理解和运用事务隔离级别,以提升数据库应用的一致性和性能。
119 2
【MySQL】黑悟空都掌握的技能,数据库隔离级别全攻略
|
3天前
|
SQL Oracle 关系型数据库
详解 MySQL 的事务以及隔离级别
详解 MySQL 的事务以及隔离级别
9 0
|
21天前
|
SQL 关系型数据库 MySQL
MySQL技术安装配置、数据库与表的设计、数据操作解析
MySQL,作为最流行的关系型数据库管理系统之一,在WEB应用领域中占据着举足轻重的地位。本文将从MySQL的基本概念、安装配置、数据库与表的设计、数据操作解析,并通过具体的代码示例展示如何在实际项目中应用MySQL。
62 0
|
2月前
|
SQL 存储 关系型数据库
mysql加索引真的会锁表吗?揭秘背后的技术细节与规避策略
【8月更文挑战第16天】在数据库管理中,添加索引能大幅提升查询效率。MySQL执行此操作时的锁定行为常引起关注。文章详细解析MySQL中索引添加时的锁定机制及其原理。不同存储引擎及SQL语句影响锁定策略:MyISAM需全表锁定;InnoDB提供更灵活选项,如使用`ALTER TABLE... LOCK=NONE`可在加索引时允许读写访问,尽管可能延长索引构建时间。自MySQL 5.6起,在线DDL技术可进一步减少锁定时间,通过`ALGORITHM=INPLACE`和`LOCK=NONE`实现近乎无锁的表结构变更。合理配置这些选项有助于最小化对业务的影响并保持数据库高效运行。
147 4
|
2月前
|
算法 关系型数据库 MySQL
一天五道Java面试题----第七天(mysql索引结构,各自的优劣--------->事务的基本特性和隔离级别)
这篇文章是关于MySQL的面试题总结,包括索引结构的优劣、索引设计原则、MySQL锁的类型、执行计划的解读以及事务的基本特性和隔离级别。
|
2月前
|
前端开发 数据挖掘 关系型数据库
基于Python的哔哩哔哩数据分析系统设计实现过程,技术使用flask、MySQL、echarts,前端使用Layui
本文介绍了一个基于Python的哔哩哔哩数据分析系统,该系统使用Flask框架、MySQL数据库、echarts数据可视化技术和Layui前端框架,旨在提取和分析哔哩哔哩用户行为数据,为平台运营和内容生产提供科学依据。
|
3月前
|
SQL 关系型数据库 MySQL
(七)MySQL事务篇:ACID原则、事务隔离级别及事务机制原理剖析
众所周知,MySQL数据库的核心功能就是存储数据,通常是整个业务系统中最重要的一层,可谓是整个系统的“大本营”,因此只要MySQL存在些许隐患问题,对于整个系统而言都是致命的。
下一篇
无影云桌面