0

0

mysql创建数据库时如何设置事务隔离级别_mysql设置事务隔离级别指南

雪夜

雪夜

发布时间:2025-09-04 17:37:02

|

350人浏览过

|

来源于php中文网

原创

MySQL默认事务隔离级别为REPEATABLE READ,通过SET语句可设置全局、会话或事务级隔离级别,分别影响所有新会话、当前会话或单个事务,需根据一致性与性能权衡选择。

mysql创建数据库时如何设置事务隔离级别_mysql设置事务隔离级别指南

MySQL在创建数据库时,实际上并不直接设置事务隔离级别。事务隔离级别是针对整个MySQL服务器实例(全局)、特定客户端会话(会话级)或单个事务(事务级)来配置的。默认情况下,InnoDB存储引擎的事务隔离级别是

REPEATABLE READ
。因此,如果你想调整隔离级别,需要通过
SET
语句来操作,而不是在
CREATE DATABASE
命令中。

解决方案

要设置MySQL的事务隔离级别,你有三种主要方式,它们分别影响不同的范围:

  1. 全局设置 (Global Setting): 影响所有新建立的会话。已存在的会话不会受到影响。

    SET GLOBAL transaction_isolation = 'READ COMMITTED';
    -- 或者其他级别:'READ UNCOMMITTED', 'REPEATABLE READ', 'SERIALIZABLE'

    这个操作需要

    SUPER
    权限。

  2. 会话级设置 (Session Setting): 仅影响当前客户端会话。当会话结束时,设置会失效。

    SET SESSION transaction_isolation = 'READ COMMITTED';
  3. 事务级设置 (Transaction Setting): 仅对紧随其后的一个事务有效。这种方式通常在

    START TRANSACTION
    语句中指定。

    START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
    -- ... 执行你的事务操作 ...
    COMMIT;

    如果不在

    START TRANSACTION
    中指定,也可以在事务开始前设置,但这种方式容易混淆,不如直接在
    START TRANSACTION
    中明确。

理解这三者的作用域非常重要。通常,我们会让服务器保持一个合理的全局默认值,然后在特定需要更高或更低隔离级别的地方,通过会话级或事务级进行调整。

MySQL事务隔离级别有哪些,它们分别解决了什么问题?

在MySQL,特别是InnoDB存储引擎中,我们有四种标准的事务隔离级别,它们在数据一致性和并发性能之间做出了不同的权衡。从低到高,它们分别是:

  • READ UNCOMMITTED (读未提交)

    • 解决了什么问题? 几乎没有。
    • 特点: 这是最低的隔离级别,一个事务可以读取到另一个事务尚未提交的数据,这被称为“脏读”(Dirty Read)。这意味着你可能会看到一个事务后来回滚了的数据。在我的实际工作中,这种隔离级别几乎不被使用,因为它带来的数据不确定性太高了,很难在业务逻辑上保证数据的正确性。
    • 场景: 极少数情况下,例如在一些对数据实时性要求极高、但对数据准确性要求不高的统计场景中可能会考虑,但风险巨大。
  • READ COMMITTED (读已提交)

    • 解决了什么问题? 解决了“脏读”问题。一个事务只能看到其他事务已经提交的数据。
    • 特点: 这是许多其他数据库(如PostgreSQL、SQL Server)的默认隔离级别。它能保证你读到的数据是“干净”的,即是已提交的。然而,它仍然允许“不可重复读”(Non-Repeatable Read)和“幻读”(Phantom Read)。不可重复读指的是在一个事务内,两次读取同一行数据,结果可能不同,因为其他事务在这两次读取之间提交了对该行的修改。
    • 场景: 适用于大多数Web应用,当业务逻辑能够容忍在同一事务内多次读取同一数据可能得到不同结果时。它在并发性上通常优于
      REPEATABLE READ
      ,因为锁的持有时间可能更短。
  • REPEATABLE READ (可重复读)

    • 解决了什么问题? 解决了“脏读”和“不可重复读”问题。
    • 特点: 这是MySQL InnoDB存储引擎的默认隔离级别。它保证在一个事务的生命周期内,对同一行数据的多次读取会得到相同的结果,即使其他事务在此期间修改并提交了该行数据。MySQL通过MVCC(多版本并发控制)机制来实现这一目标。然而,它在标准SQL定义下,仍然可能出现“幻读”。幻读指的是在一个事务内,两次执行相同的范围查询(例如
      SELECT ... WHERE id > 10
      ),第二次查询可能会发现有新的行插入进来,因为其他事务提交了新的插入操作。值得一提的是,MySQL的
      REPEATABLE READ
      在很大程度上通过Next-Key Locks(间隙锁+行锁)避免了幻读,尤其是在
      UPDATE
      DELETE
      操作中。但在某些
      INSERT
      场景下,幻读依然可能发生,这需要我们开发者在设计时加以注意。
    • 场景: 适合大多数需要强一致性保证的OLTP(在线事务处理)应用,例如银行交易、库存管理等,其中事务内的数据一致性至关重要。
  • SERIALIZABLE (串行化)

    • 解决了什么问题? 解决了所有并发问题,包括脏读、不可重复读和幻读。
    • 特点: 这是最高的隔离级别,它强制事务串行执行,即任何时候只有一个事务在读写数据。它通过对所有读写操作都加锁来实现,这会大大降低数据库的并发性能。
    • 场景: 只有在对数据一致性要求极高,且可以接受显著的性能牺牲时才考虑使用。在我看来,它通常是作为“终极保障”而存在,实际生产环境中很少直接用作默认级别。

为什么MySQL的InnoDB默认事务隔离级别是REPEATABLE READ?它有什么优势和潜在挑战?

MySQL的InnoDB存储引擎选择

REPEATABLE READ
作为默认隔离级别,我认为这背后有其深思熟虑的设计哲学,它试图在数据一致性和并发性能之间找到一个相对较好的平衡点,并与InnoDB的MVCC机制紧密结合。

优势:

  1. 强一致性保证:
    REPEATABLE READ
    确保了在一个事务中,你对同一数据的多次读取会看到一个一致的版本。这对于许多业务逻辑来说至关重要,比如在一个复杂的计算或报表生成过程中,你需要确保所有相关数据在事务开始时是“冻结”的,不会因为其他并发事务的提交而发生变化。这大大简化了应用层的数据同步和验证逻辑。
  2. MVCC的良好支持: InnoDB的MVCC机制在
    REPEATABLE READ
    下表现得淋漓尽致。对于普通的
    SELECT
    查询,MVCC允许读取旧版本的数据,从而避免了读写冲突,提高了并发度。只有在涉及到
    UPDATE
    DELETE
    等写操作时,才需要加锁,并且这些锁通常是行级的,粒度较细。
  3. 防止数据逻辑错误: 在许多关键业务场景中,例如转账操作,如果两次读取余额不一致,可能会导致严重的逻辑错误。
    REPEATABLE READ
    有效地避免了这类问题,提供了更可靠的事务语义。

潜在挑战:

  1. 幻读的细微之处: 尽管MySQL的
    REPEATABLE READ
    通过Next-Key Locks在大多数情况下避免了幻读,但它并非完全免疫。例如,如果你在一个事务中执行
    SELECT COUNT(*)
    ,然后另一个事务插入了新行并提交,接着你再次执行
    SELECT COUNT(*)
    ,你可能会看到不同的结果(幻读)。这主要是因为MVCC对读操作是快照隔离,而Next-Key Locks主要针对
    UPDATE
    DELETE
    SELECT ... FOR UPDATE
    。这种微妙的行为有时会让不熟悉MySQL隔离机制的开发者感到困惑。
  2. 可能增加锁竞争: 相较于
    READ COMMITTED
    REPEATABLE READ
    为了维护其一致性视图,可能会持有锁更长时间,或者在某些情况下需要更强的锁(例如Next-Key Locks)。这在极高并发的写入场景下,可能会导致更多的锁等待和死锁,从而影响性能。我曾遇到过一些高并发场景,为了减少锁竞争,不得不将隔离级别降至
    READ COMMITTED
    ,但这需要非常谨慎地评估业务风险。
  3. MVCC开销: 维护多版本数据会带来额外的存储和CPU开销,例如需要清理旧版本数据(Purge)。虽然InnoDB在这方面做得很好,但在数据量巨大、更新频繁的场景下,这也可能成为性能瓶颈的一部分。

总的来说,

REPEATABLE READ
是一个强大的默认选项,它为大多数应用提供了可靠的数据一致性。但作为开发者,我们不能盲目依赖它,理解其工作原理和潜在的“陷阱”至关重要,尤其是在处理高并发和复杂数据操作时。

Haiper
Haiper

一个感知模型驱动的AI视频生成和重绘工具,提供文字转视频、图片动画化、视频重绘等功能

下载

如何根据应用场景选择合适的事务隔离级别?有没有具体的代码示例?

选择合适的事务隔离级别是一个权衡的过程,需要在数据一致性、并发性能和开发复杂性之间找到最佳点。我的经验告诉我,没有一个“放之四海而皆准”的答案,关键在于深入理解你的应用需求。

以下是一些基于常见应用场景的选择建议和代码示例:

  1. 默认起点:REPEATABLE READ (MySQL InnoDB默认)

    • 场景: 大多数OLTP应用,特别是那些对事务内数据一致性要求较高,且能接受MySQL
      REPEATABLE READ
      特性(包括对幻读的特殊处理)的应用。如果你不确定,从这个级别开始总是没错的。它提供了一个很好的平衡点。
    • 何时考虑改变? 只有当你明确遇到性能瓶颈(如锁等待、死锁增多)或业务逻辑确实需要更宽松(如
      READ COMMITTED
      )或更严格(如
      SERIALIZABLE
      )的一致性时,才去调整。
    • 代码示例:
      -- 查看当前会话的隔离级别
      SELECT @@SESSION.transaction_isolation;
      -- 如果是默认,通常会显示 'REPEATABLE-READ'
  2. 高并发、对实时性要求高但允许轻微不一致:READ COMMITTED

    • 场景: 许多Web应用或API服务,其中单个请求通常对应一个短事务。如果应用可以容忍在同一个事务中,多次读取同一行数据时,可能会看到其他事务提交的最新版本(不可重复读),那么

      READ COMMITTED
      可以提供更高的并发性能,因为它持有锁的时间更短。这在一些高并发的电商库存查询、用户评论发布等场景中可能适用。

    • 何时不适用? 如果你的业务逻辑依赖于事务内多次读取同一数据必须保持一致,或者有复杂的统计/聚合查询,那么

      READ COMMITTED
      可能导致逻辑错误。

    • 代码示例:

      -- 在会话级别设置
      SET SESSION transaction_isolation = 'READ COMMITTED';
      
      -- 或者,如果你想全局设置(谨慎操作,会影响所有新连接)
      -- SET GLOBAL transaction_isolation = 'READ COMMITTED';
  3. 极高并发、数据不敏感或日志记录:READ UNCOMMITTED

    • 场景: 这种隔离级别非常罕见,通常只用于一些对数据准确性要求极低,但对读取速度要求极高,且能容忍“脏读”的场景。例如,一些非关键的实时监控系统,或者临时性的日志分析,即使读到一些未提交的数据也无所谓。
    • 何时不适用? 几乎所有涉及业务逻辑和数据完整性的场景都不应使用。
    • 代码示例:
      SET SESSION transaction_isolation = 'READ UNCOMMITTED';
  4. 数据一致性要求最高,不惜牺牲性能:SERIALIZABLE

    • 场景: 极端情况下,例如金融交易的核心账务系统、关键库存的精确扣减(尽管通常可以通过乐观锁或更精细的行锁设计来避免),或者任何需要绝对避免所有并发问题的场景。这种级别会强制事务串行执行,导致并发度急剧下降,可能成为严重的性能瓶颈。

    • 何时不适用? 几乎所有对性能有一定要求的应用都不适合。

    • 代码示例:

      -- 在单个事务中指定,这是最常见的用法
      START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
      -- ... 执行关键的事务操作 ...
      COMMIT;
      
      -- 或者在会话级别设置 (同样谨慎)
      -- SET SESSION transaction_isolation = 'SERIALIZABLE';

总结与个人建议:

我通常建议从MySQL的默认

REPEATABLE READ
开始。这个级别在大多数情况下提供了足够的事务隔离,并且通过MVCC机制在读操作上表现良好。如果遇到性能问题,首先应该检查SQL语句的优化、索引设计、应用层面的锁机制,而不是急于降低隔离级别。只有在明确理解了不同隔离级别带来的风险和收益后,才考虑进行调整。

例如,一个典型的电商订单处理流程:

-- 假设我们在一个会话中,默认是 REPEATABLE READ
-- 开启事务
START TRANSACTION;

-- 1. 检查库存 (REPEATABLE READ 保证多次读取库存一致)
SELECT stock_quantity FROM products WHERE product_id = 123 FOR UPDATE; -- FOR UPDATE 显式加行锁,防止其他事务修改

-- 如果库存不足,回滚
-- IF stock_quantity < order_quantity THEN
--   ROLLBACK;
-- ELSE
--   2. 扣减库存
--   UPDATE products SET stock_quantity = stock_quantity - order_quantity WHERE product_id = 123;
--
--   3. 创建订单
--   INSERT INTO orders (user_id, product_id, quantity, status) VALUES (1, 123, order_quantity, 'pending');
--
--   4. 提交事务
--   COMMIT;
-- END IF;

在这个例子中,

REPEATABLE READ
配合
FOR UPDATE
能够提供非常强的一致性,确保库存检查和扣减在一个原子操作中完成,有效避免了超卖问题。如果没有
FOR UPDATE
,仅仅依靠
REPEATABLE READ
,虽然能保证两次
SELECT
库存结果一致,但不能阻止其他事务在
SELECT
UPDATE
之间修改库存,导致超卖。这说明,隔离级别只是事务管理的一部分,有时还需要配合显式锁来解决特定的并发问题。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

675

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

319

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

345

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1084

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

355

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

673

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

566

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

409

2024.04.29

php源码安装教程大全
php源码安装教程大全

本专题整合了php源码安装教程,阅读专题下面的文章了解更多详细内容。

7

2025.12.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.3万人学习

Django 教程
Django 教程

共28课时 | 2.6万人学习

Excel 教程
Excel 教程

共162课时 | 10.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号