慣性聚合 関心のあるブログ、ニュース、テクノロジーを効率的に追跡
原文を読む 慣性聚合で開く

おすすめ購読元

小众软件
小众软件
博客园 - 叶小钗
有赞技术团队
有赞技术团队
大猫的无限游戏
大猫的无限游戏
博客园_首页
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
L
LangChain Blog
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
aimingoo的专栏
aimingoo的专栏
Blog — PlanetScale
Blog — PlanetScale
爱范儿
爱范儿
T
Tailwind CSS Blog
Jina AI
Jina AI
量子位
Stack Overflow Blog
Stack Overflow Blog
人人都是产品经理
人人都是产品经理
J
Java Code Geeks
V
Visual Studio Blog
月光博客
月光博客

博客园 - lzhdim

10个不该免费的GitHub神级项目 JavaScript语言全面概述:从历史到现代实践 一张图看懂常见咖啡 C盘空间多出来4GB:谷歌服软 Chrome本地AI大模型可禁用、删除了 96GB显存运行230B大模型!七彩虹灵创K16笔记本评测:160W性能释放 AMD锐龙AI Max+ 395加持全能移动AI工作站 AI PC最强存储搭档!雷克沙NM1090 PRO 8TB固态评测:14400MB/s满速不缩水 C#已经不是当年的C#了——我用它写了个微秒级数据库引擎 EasyTool:轻量全能的 .NET 工具类库 SQL 入门 17:MySQL 数据类型:从字符串到 JSON 的全面解析 原相3955XM+TL3228主控!小米电竞鼠标2全面评测:原生双8K究竟有多强 PCIe 4.0火力全开:闪迪奥丁马仕GX 7100 NVMe SSD上手 超乎预料的千元级电竞主板!七彩虹iGame B850M Ultra-OC V14主板评测 SQL 入门 15:SQL 事务:从 ACID 到四种常见的并发问题 名人 - 我的闪存 C#性能优化技巧 SQL 入门 14:SQL 触发器与事件:自动化数据处理 38个实用的JavaScript 技巧 一款基于 .Net WinForm 开发的节点编辑器,纯 GDI 实现,体积仅 100+Kb Masuit.Tools:这个 C# 工具库 SQL 入门 13:SQL 存储过程与函数:封装逻辑与参数处理 49个 JavaScript 代码快捷技巧,让你在 2026 年成为代码高手 20260503 - 个人小作品更新 - lzhdim SQL 入门 12:SQL 视图:创建、修改与可更新视图 C#如何实现Windows系统桌面截图功能... 6999元AMD新旗舰首测!锐龙9 9950X3D2性能解禁:这颗U根本不是给游戏玩家造的 SQL 入门 11:日期时间格式化、IF、CASE的使用 基于C#的校时类库的实现及使用 - 开源项目研究文章 39g无打孔+原生双8K!雷柏VT0 Air MAX / VT3s Air MAX鼠标评测:轻到飞起还快到极致 WinForm 中控件自适应窗体变化 20260413 - 个人小作品更新 SQL 入门 10:SQL 内置函数:数值、字符串与时间处理 最强麒麟芯+自研风冷 华为Mate80 Pro MAX 风驰版全面评测:涡轮散热封神 性能稳到骨子里 WiFi8核心技术特性与性能分析 2026年最新AMD/Intel桌面CPU排名:多线程、单线程、游戏性能谁才是第一 用DG对C盘进行扩容 - 初学者系列 - 学习者系列 还有比它更强的OEM固态吗!长江存储PC550 1TB评测:不用散热片也能满速的PCIe 5.0 SSD - lzhdim SharpCompress:跨平台的 C# 压缩与解压库 - lzhdim SQL 入门 9:SQL 高级子查询:ANY、EXISTS 与多位置应用 - lzhdim 盘点接私活20个最实用的 .NET 开源项目 - lzhdim C#中加载图片的资源释放 - lzhdim 20260404 - 个人小作品更新 - lzhdim 开启iphone的墙纸玻璃效果 - lzhdim 可能是综合性能最强的PCIe 5.0 SSD!铠侠EXCERIA PRO G2 2TB评测:AIDA64线性写入全程不掉速 SQL 入门 8:SQL 复杂查询:子查询与ALL关键词 - lzhdim 性能最强的锐龙AI 9 H 465轻薄本!华硕无畏Pro16锐龙版2026评测 4盘RAID 0读写超1100MB/s!希捷酷狼Pro 32TB硬盘评测:百万文件快速完成备份 - lzhdim 项目(Project)、项目集(Program)、项目组合(Portfolio) SQL 入门 7:SQL 聚合与分组:函数、GROUP BY 与 ROLLUP
SQL 入門 16:SQL トランザクションの分離レベルとデッドロックの解析(分かりやすい)
lzhdim · 2026-05-28 · via 博客园 - lzhdim

トランザクションの分離レベルはデータベースの並行制御の核心であり、トランザクション間の分離方法や、一つのトランザクションが他のトランザクションの変更をどの程度見ることができるかを定義しています。本稿では sql_store データベースを基に、コード例を通じてMySQLがサポートする4種類の標準的なトランザクション分離レベルとその影響を詳細に解説し、シナリオを用いて分離レベルの役割を説明し、死锁問題とその回避方法を解析することで、読者がトランザクションの並行管理を深く理解するのを助けます。

学習内容

1. トランザクション分離レベルの概要

MySQLは4種類の標準的なトランザクション分離レベルをサポートしており、低い順に以下の通りです:

  • 読み取り未コミット(READ UNCOMMITTED)
    最も低い分離レベルであり、トランザクションは他のトランザクションが未コミットにした変更を読み取ることができます。これにより汚染読み問題が発生します。性能は最も高いですが、汚染読み、重複読み、幻覚読みが発生する可能性があります。
  • 読み取り済み(READ COMMITTED)
    トランザクションは既にコミットされた変更のみを読み取るため、汚染読み取りを回避できるが、重複読み取りや幻読が発生する可能性がある。多くのデータベース(Oracle、PostgreSQLなど)のデフォルトのレベル。
  • 一貫性のある読み取り(REPEATABLE READ)
    MySQL InnoDB のデフォルトの分離レベルで、マルチバージョン並列制御(MVCC)と隙間ロックを通じて、同じトランザクション内で複数回同じデータを読み取る結果が一貫していることを保証し、汚染読み取りや重複読み取りを回避できるが、幻読が発生する可能性がある(InnoDB はロック機構によって部分的に緩和)。
  • 順序化(SERIALIZABLE)
    最も高い隔離レベルで、トランザクションを順次実行強制し、汚染読み取り、不整合読み取り、幻読を完全に回避しますが、性能は最も低いです。

隔離レベルが高いほど、並列性能は低くなりますが、データ整合性は高くなります。ATM 転账シナリオでは、適切な隔離レベルを設定することで、口座残高の更新が他のトランザクションによって干渉されないように保証できます。

2. 隔離レベルの確認と設定

  SHOW VARIABLES LIKE 'transaction_isolation'  で現在の隔離レベルを確認し、デフォルトでは  REPEATABLE-READ__が表示されます。以下のステートメントを使用して隔離レベルを設定できます:

  • SET TRANSACTION ISOLATION LEVEL < レベル>:次のトランザクションに影響します。
  • SET SESSION TRANSACTION ISOLATION LEVEL <レベル>:現在のセッションに影響します。
  • SET GLOBAL TRANSACTION ISOLATION LEVEL <レベル>:新しいセッション全体に影響します。

3. 並行問題と隔離レベル

異なる隔離レベルは汚染読み取り、不整合読み取り、幻読み取りの制御能力が異なります:

  • 汚染読み取り:未コミットデータを読み取ることで、誤った判断が生じる可能性があります。
  • 不整合読み取り:同じトランザクション内で複数回クエリを実行した結果が一致しない場合、他のトランザクションが変更をコミットしたためです。
  • 幻読み取り:同じトランザクション内でクエリ範囲の行数が変わる場合、他のトランザクションが行を挿入または削除したためです。

4. 死锁

死锁は、並行トランザクションで複数のトランザクションがお互いのリソースを解放するのを待っている状態で、実行を続けることができない状態です。MySQL は死锁を検出し、一つのトランザクションを終了させ、エラーメッセージを表示します。死锁を減らすには、一貫したリソースアクセス順序を保つか、トランザクションの長さを短くすることが必要です。

サンプルコードと解説

1. 隔離レベルの確認

ショー 変数 のよう 'transaction_isolation';

は現在の分離レベルを表示し、デフォルト値は REPEATABLE-READであり、MySQL InnoDBの標準設定です。

2. 分離レベルの設定

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

は現在のセッションの分離レベルを SERIALIZABLEに設定し、以降のトランザクションを順次実行させ、すべての並行問題を回避します。

3. 読み取り未コミット(READ UNCOMMITTED)

コンソール 1

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT points FROM 顧客 WHERE 顧客ID = 1;

コンソール 2

START TRANSACTION;
UPDATE 顧客 SET ポイント = 20 WHERE 顧客ID 1;
-- 未コミット

でコンソール1で READ UNCOMMITTED を設定した後、顧客1のポイント(元は2303)をクエリします。コンソール2はポイントを20に更新しコミットせず、コンソール1が再度クエリすると20が表示され、汚染読み取りが現れます。もしコンソール2がロールバックされると、コンソール1のクエリ結果は無効になり、業務判断を誤引导する可能性があります。

4. 読み取りコミット(READ COMMITTED)

コンソール1

SET TRANSACTION ISOLATION レベル 読み取り コミット済み;
SELECT ポイント FROM 顧客 WHERE 顧客ID = 1;

コンソール 2

START トランザクション;
UPDATE 顧客 SET ポイント = 20 WHERE 顧客ID = 1;
コミット;

コンソール 1 で READ コミットテッド を設定した後、ポイントをクエリします。コンソール 2 で変更がコミットされていない場合、コンソール 1 は元の値 2303 をまだ見ることができ、汚染読みを防ぎます。コンソール 2 がコミットされると、コンソール 1 はクエリして 20 を取得します。しかし、同じトランザクション内で複数回クエリした場合、他のトランザクションがコミットされることで結果が一貫しなくなり、不重複読みが発生する可能性があります。

コンソール 1(再読み出し不可の例)

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT points FROM customers WHERE customer_id = 1;
-- 戻り値 20
SELECT points FROM customers WHERE customer_id = 1;
-- 戻り値 30
COMMIT;

コンソール 2

START TRANSACTION;
UPDATE customers SET points = 30 WHERE customer_id = 1;
COMMIT;

コンソール1 最初のクエリで20が取得され、コンソール2でコミット後に更新され30になる、コンソール1の2回目のクエリで30が取得され、不重複読み取りが現れ、データの整合性が影響を受ける。

5. 複数回読(REPEATABLE READ)

コンソール 1

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT points FROM 顧客 WHERE customer_id = 1;
-- 30を返します
SELECT points FROM 顧客 WHERE customer_id = 1;
-- まだ30を返します
コミット;

コンソール 2

スタート トランザクション;
アップデート customers セット points = 40 ウェhre customer_id = 1;
コミット;

において 一貫性読み取り の下、コンソール1ではトランザクション開始時に一貫性の視点が作成され、トランザクション開始時のスナップショットに基づいています(積分は30です)。コンソール2では変更が40にコミットされますが、コンソール1の2回目のクエリではまだ30が返され、不整合読み取りを回避します。MVCCはトランザクション内のデータの一貫性を保証します。

幻読の例

コンソール1

SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
トランザクションを開始 ;
 * を customers から選択 して、 stateが
'CO'のものをフィルタリング
コミット

開始 TRANSACTION;
UPDATE customers SET state = 'CO' WHERE customer_id = 1;
COMMIT;

コンソール 1 検索 state = 'CO' の顧客は初期状態で1件の記録しかありません。コンソール2で顧客1の状態を'CO'に変更し、コミットします。コンソール1がトランザクションをコミットした後再度クエリを実行しても、依然として1件の記録しか返されず、データベースの最新状態が反映されません。これにより幻読が発生します。InnoDBの隙間ロックは幻読を部分的に緩和できます。

6. 串行化(SERIALIZABLE)

コンソール1

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
START TRANSACTION;
SELECT * FROM customers WHERE state = 'CO';
COMMIT;

コンソール 2

START TRANSACTION;
UPDATE customers SET ステート = 'CO' どこに カスタマーID 2;
コミット

において SERIALIZABLE 下で、コンソール1をクエリします state = 'CO' 顧客(初期2件)。コンソール2は顧客2の状態を'CO'に変更しようと試みましたが、コミットできませんでした。コンソール1のトランザクションはコンソール2のコミットを待ってブロックされ、幻読を防ぎます。コミット後、コンソール1は最新のデータを正確に反映します。

7. 死锁

コンソール 1

START TRANSACTION;
UPDATE customers SET state = 'VA' WHERE customer_id = 1;
UPDATE orders SET status = 1 WHERE order_id = 1;
COMMIT;

コンソール 2

START TRANSACTION;
UPDATE orders SET status = 1 WHERE order_id = 1;
UPDATE customers SET state = 'VA' WHERE customer_id = 1;
COMMIT;

コンソール 1 ロック customers の行で、 ordersをロックしようと試み、コンソール2が ordersをロックし、 customersをロックしようとするが、循環依存を形成し、デッドロックを引き起こす。MySQLはデッドロックを検知すると、一つのトランザクションを終了し、エラーメッセージを表示する。デッドロックを回避するには、リソースアクセス順序を統一するか、トランザクション長を短縮する必要がある。

トランザクションの分離レベルが並行トランザクションのデータの可視性と一貫性を決定する。READ UNCOMMITTED は性能が高いがリスクが大きく、SERIALIZABLE は安全だが性能が低く、REPEATABLE READ はMySQL InnoDBのデフォルトの妥協案である。ATM转账シナリオは分離レベルがデータの一貫性に与える重要性を示している。本稿は sql_store データベース、コード例を通じて四つの隔離レベルと死锁問題を解析します。後続のコンテンツでは、インデックス設計やクエリ最適化について探求し、ご注目ください。