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

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
日志服务 SLS,月写入数据量 50GB 1个月
简介: 【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
目录
相关文章
|
4月前
|
监控 关系型数据库 MySQL
10亿数据如何最快速插入MySQL:技术干货分享
【8月更文挑战第2天】在大数据时代,处理并快速插入数十亿条数据到MySQL数据库是许多企业面临的关键挑战。本文将深入分享一系列高效的技术策略和实战经验,帮助读者优化这一过程,确保数据能够快速、准确地进入数据库系统。
220 1
|
11天前
|
JavaScript 安全 Java
java版药品不良反应智能监测系统源码,采用SpringBoot、Vue、MySQL技术开发
基于B/S架构,采用Java、SpringBoot、Vue、MySQL等技术自主研发的ADR智能监测系统,适用于三甲医院,支持二次开发。该系统能自动监测全院患者药物不良反应,通过移动端和PC端实时反馈,提升用药安全。系统涵盖规则管理、监测报告、系统管理三大模块,确保精准、高效地处理ADR事件。
|
2月前
|
存储 SQL 关系型数据库
MySQL的事务隔离级别
【10月更文挑战第17天】MySQL的事务隔离级别
120 43
|
27天前
|
监控 前端开发 Java
【技术开发】接口管理平台要用什么技术栈?推荐:Java+Vue3+Docker+MySQL
该文档介绍了基于Java后端和Vue3前端构建的管理系统的技术栈及功能模块,涵盖管理后台的访问、登录、首页概览、API接口管理、接口权限设置、接口监控、计费管理、账号管理、应用管理、数据库配置、站点配置及管理员个人设置等内容,并提供了访问地址及操作指南。
|
1月前
|
监控 关系型数据库 MySQL
MySQL自增ID耗尽应对策略:技术解决方案全解析
在数据库管理中,MySQL的自增ID(AUTO_INCREMENT)属性为表中的每一行提供了一个唯一的标识符。然而,当自增ID达到其最大值时,如何处理这一情况成为了数据库管理员和开发者必须面对的问题。本文将探讨MySQL自增ID耗尽的原因、影响以及有效的应对策略。
100 3
|
18天前
|
关系型数据库 MySQL 数据库
MySQL事务隔离级别及默认隔离级别的设置
在数据库系统中,事务隔离级别是一个关键的概念,它决定了事务在并发执行时如何相互隔离。MySQL提供了四种事务隔离级别,每种级别都解决了不同的并发问题。本文将详细介绍这些隔离级别以及MySQL的默认隔离级别。
|
2月前
|
存储 关系型数据库 MySQL
RR隔离级别在MySQL中的实现与幻读问题探讨
【10月更文挑战第3天】在数据库管理系统中,事务隔离级别是确保数据一致性和并发性能的关键要素。MySQL作为广泛使用的关系型数据库管理系统,支持多种事务隔离级别,其中可重复读(Repeatable Read,简称RR)是其默认隔离级别。本文将深入探讨RR隔离级别在MySQL中的实现原理,以及RR隔离级别下幻读问题的产生与解决方案。
111 2
|
2月前
|
XML 关系型数据库 MySQL
MySQL 导出某些数据的技术详解
MySQL 导出某些数据的技术详解
151 2
|
3月前
|
关系型数据库 MySQL 数据库
深入理解MySQL数据库隔离级别
深入理解MySQL数据库隔离级别
138 1
|
3月前
|
存储 关系型数据库 MySQL
技术解析:MySQL中取最新一条重复数据的方法
以上提供的两种方法都可以有效地从MySQL数据库中提取每个类别最新的重复数据。选择哪种方法取决于具体的使用场景和MySQL版本。子查询加分组的方法兼容性更好,适用于所有版本的MySQL;而窗口函数方法代码更简洁,执行效率可能更高,但需要MySQL 8.0及以上版本。在实际应用中,应根据数据量大小、查询性能需求以及MySQL版本等因素综合考虑,选择最合适的实现方案。
414 6