目次
定義
標準 SQL 分離レベル
実装原則
標準 SQL トランザクション分離レベルの実装原則
InnoDB トランザクション分離レベルの実装原則
一些常见误区
幻读到底包不包括了delete的情况?
MVCC能解决了幻读问题?
ホームページ データベース mysql チュートリアル MySQL のトランザクション分離レベルの簡単な分析とその実装原則の説明

MySQL のトランザクション分離レベルの簡単な分析とその実装原則の説明

Mar 08, 2022 am 10:21 AM
mysql 事務 分離レベル

この記事では、MySQL のトランザクションを理解し、トランザクション分離の実装原理について説明します。お役に立てば幸いです。

MySQL のトランザクション分離レベルの簡単な分析とその実装原則の説明

データベース トランザクションと言えば、トランザクションの ACID 特性、分離レベル、解決された問題など、多くのトランザクション関連の知識が誰の頭にも容易に浮かぶはずです。 (ダーティ リード、ノンリピータブル リード、ファントム リード) などがありますが、トランザクションのこれらの機能がどのように実装されているか、およびなぜ 4 つの分離レベルがあるのか​​を実際に知っている人はほとんどいないかもしれません。

今日はまず、MySQL におけるトランザクション分離の実装原理について説明し、引き続き他の機能の実装原理を分析する記事を公開していきます。

もちろん、MySQL は広範囲かつ奥が深いため、記事の省略は避けられません。批判や修正は歓迎です。

説明

MySQL のトランザクション実装ロジックはエンジン層にあり、すべてのエンジンがトランザクションをサポートしているわけではありません。次の手順は InnoDB エンジンに基づいています。

定義

分離とは、さまざまなトランザクションが次々に送信されて実行された後、最終的な影響は連続的であるという事実を指します。つまり、トランザクションの場合、それは実行中です。このプロセスでは、認識されるデータの変更は自分自身の操作によってのみ発生する必要があり、他のトランザクションによってデータの変更が発生してはなりません。

分離により、同時トランザクションの問題が解決されます

標準 SQL 分離レベル

分離を実装する最も簡単な方法は、各トランザクションをシリアルに実行することです。前のトランザクションが完了していない場合、後続のトランザクションは待機します。ただし、この実装方法は明らかに同時実行効率が低く、実際の環境での使用には適していません。

上記の問題を解決し、さまざまなレベルの同時実行制御を実現するために、SQL 標準の作成者は、非コミット読み取り (コミットされていない読み取り)、コミット読み取り (コミットされた読み取り)、反復可能読み取り (反復可能) 読み取りというさまざまな分離レベルを提案しました。 )、シリアル化された読み取り (シリアル化可能)。最も高度な分離レベルはシリアル化読み取りであり、他の分離レベルではトランザクションが同時に実行されるため、ある程度の問題は許容されます。次のマトリックス表を参照してください。

##繰り返し不可能なリード ## Serialized Readingを読むために

MySQL の InnoDB エンジンは、繰り返し読み取りレベルのギャップ ロックを通じてファントム読み取り問題を解決し、MVCC を通じて非繰り返し読み取り問題を解決することに注意してください。詳細については、 以下の分析を参照してください。

実装原則

標準 SQL トランザクション分離レベルの実装原則

上で遭遇した問題は、実際には同時トランザクションでの制御の問題です。同時トランザクションを解決する最も一般的な方法は次のとおりです。悲観的な同時実行制御 (つまり、データベースのロック)。標準 SQL トランザクション分離レベルの実装はロックに依存しています。その実装方法を見てみましょう:

#分離レベル (: 表示を許可、-: 表示を許可しない) ダーティ リード ##ファンタジー リード ## ##
##トランザクション分離レベル 実装方法 #非コミット読み取り (RU) コミット読み取り (RC) 行レベルの共有ロックを追加します (読み取り時のみロックされます) リピータブル リード (RR) 行を追加する必要があります。 レベル共有ロックシリアル化読み取り (S) テーブル レベルの共有ロック

ロックのみを使用して分離レベル制御を実装する場合、頻繁なロックとロック解除が必要となり、読み取りと書き込みの競合が発生しやすいことがわかります (たとえば、RC レベルでは、トランザクション A がデータ行 1 を更新し、トランザクション B は、トランザクション A がデータ行の読み取りをコミットする前に、トランザクション A がコミットしてロックを解放するまで待機する必要があります 1)。

ロックを行わずに読み取り/書き込み競合の問題を解決するために、MySQL は MVCC メカニズムを導入しました。詳細については、以前の分析記事「データベース内の楽観的ロック、悲観的ロック、および MVCC を 1 つの記事で理解する」を参照してください。 。

InnoDB トランザクション分離レベルの実装原則

分析を進める前に、まず理解しておく必要がある概念がいくつかあります:

1. 読み取りのロックと一貫性非ロック読み取り

ロック読み取り: トランザクション内で、SELECT ... LOCK IN SHARE MODE や SELECT ... FOR UPDATE など、読み取りをアクティブにロックします。行共有ロックと行排他ロックがそれぞれ追加されます。ロックの分類については、以前の分析記事「知っておくべき MySQL ロックの分類」を参照してください。

https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html

一貫した非ロック読み取り: InnoDB MVCC を使用して、トランザクションのクエリに対して特定の時点でのデータベースのスナップショットを提供します。クエリでは、その時点より前にコミットされたトランザクションによって行われた変更は確認されますが、それ以降のトランザクションまたはコミットされていないトランザクション (このトランザクション以外) によって行われた変更は確認されません。つまり、トランザクションの開始後、トランザクションによって表示されるデータは、トランザクションが開始された時点のデータであり、その後の他のトランザクションの変更は、このトランザクションでは表示されません。

一貫性のある読み取りは、RC および RR 分離レベルで SELECT ステートメントを処理する InnoDB のデフォルト モードです。一貫した非ロック読み取りでは、アクセスするテーブルにロックが設定されないため、テーブルに対して一貫した非ロック読み取りを実行している間、他のトランザクションはそれらを同時に読み取りまたは変更できます。

https://dev.mysql.com/doc/refman/8.0/en/innodb-consistent-read.html

2. 現在の読み取りとスナップショットの読み取り

現在の読み取り

は、UPDATE、DELETE、INSERT、SELECT... LOCK IN SHARE MODE、SELECT... FOR などの最新バージョンを読み取ります。 UPDATEこれらの操作はすべて現在の読み取りです。なぜ現在の読み取りと呼ばれるのでしょうか?つまり、レコードの最新バージョンを読み取ります。読み取り時には、他の同時トランザクションが現在のレコードを変更できないようにする必要があり、読み取られたレコードはロックされます。

スナップショット読み取り

スナップショット バージョン、つまり履歴バージョンを読み取ります。ロック解除された SELECT 操作はスナップショット読み取りです。ロックを行わないノンブロッキング読み取り; スナップショット読み取りの前提条件は、アンコミット読み取りは現在のトランザクションに準拠するデータ行ではなく、常に最新のデータ行を読み取るため、分離レベルが非コミット読み取りおよびシリアル化読み取りレベルではないことです。 version とシリアル化された読み取りにより、テーブル がロックされます。

3. 暗黙的ロックと明示的ロック

暗黙的ロック

InnoDB は 2 段階のロック プロトコルを使用します (アクティブ ディスプレイなし) locking):

  • ロックはいつでも実行でき、InnoDB は分離レベルに基づいて必要に応じて自動的にロックします;
  • ロックのみコミットまたはロールバック時に解放されますが実行されると、すべてのロックが同時に解除されます。

明示的なロック

  • InnoDB は、特定のステートメント (ストレージ エンジン層) を介した明示的なロックもサポートしています。

    select ... lock in share mode //共享锁
    select ... for update //排他锁
    ログイン後にコピー
  • MySQL Server レイヤーでの表示ロック:

    lock table
    unlock table
    ログイン後にコピー

上記の概念を理解した後、InnoDB トランザクションがどのように実装されるかを見てみましょう (以下)。アクティブにロックされた選択)

トランザクションは現在読み取られているデータをロックしません; トランザクションは現在、特定のデータを更新しています大量のデータ (つまり、更新が発生した瞬間) を処理するには、最初に
行レベルの共有ロック
をデータに追加する必要があります。この共有ロックは、トランザクションが終了するまで解放されません。
トランザクションは、現在読み取られているデータに 、行が読み取られると、行レベルの共有ロックはすぐに解放されます。トランザクションが特定のデータを更新した瞬間 (つまり、更新が発生した瞬間)、最初に
row を追加する必要があります。 -レベルの排他ロック
、トランザクションが終了するまで解放されません。
トランザクションが特定のデータを読み取る瞬間 (読み取りを開始する瞬間)、まずそのデータに はトランザクションが終了するまで解放されません; トランザクションが特定のデータを更新した瞬間(つまり、更新が発生した瞬間)、最初に
行レベルの排他ロックを追加する必要があります。 lock
、トランザクションが終了するまで解放されません。
トランザクションがデータを読み取るときは、トランザクションが終了するまで、まず を追加する必要があります。 トランザクションがデータを更新するときは、まず
テーブル レベルの排他ロック
を追加する必要があります。このロックはトランザクションが終了するまで解放されません。
事务隔离级别 实现方式
未提交读(RU)事务对当前被读取的数据不加锁,都是当前读

事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级共享锁,直到事务结束才释放。
提交读(RC) 事务对当前被读取的数据不加锁,且是快照读

事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁(Record),直到事务结束才释放。
可重复读(RR)事务对当前被读取的数据不加锁,且是快照读

事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加行级排他锁(Record,GAP,Next-Key),直到事务结束才释放。

通过间隙锁,在这个级别MySQL就解决了幻读的问题

通过快照,在这个级别MySQL就解决了不可重复读的问题
序列化读(S) 事务在读取数据时,必须先对其加表级共享锁 ,直到事务结束才释放,都是当前读

事务在更新数据时,必须先对其加表级排他锁 ,直到事务结束才释放。

可以看到,InnoDB通过MVCC很好的解决了读写冲突的问题,而且提前一个级别就解决了标准级别下会出现的幻读问题,大大提升了数据库的并发能力。

一些常见误区

幻读到底包不包括了delete的情况?

不可重复读:前后多次读取一行,数据内容不一致,针对其他事务的update和delete操作。为了解决这个问题,使用行共享锁,锁定到事务结束(也就是RR级别,当然MySQL使用MVCC在RC级别就解决了这个问题)

幻读:当同一个查询在不同时间生成不同的行集合时就是出现了幻读,针对的是其他事务的insert操作,为了解决这个问题,锁定整个表到事务结束(也就是S级别,当然MySQL使用间隙锁在RR级别就解决了这个问题)

网上很多文章提到幻读和提交读的时候,有的说幻读包括了delete的情况,有的说delete应该属于提交读的问题,那到底真相如何呢?我们实际来看下MySQL的官方文档(如下)

The so-called phantom problem occurs within a transaction when the same query produces different sets of rows at different times. For example, if a SELECT) is executed twice, but returns a row the second time that was not returned the first time, the row is a “phantom” row.

https://dev.mysql.com/doc/refman/5.7/en/innodb-next-key-locking.html

可以看到,幻读针对的是结果集前后发生变化,所以看起来delete的情况应该归为幻读,但是我们实际分析下上面列出的标准SQL在RR级别的实现原理就知道,标准SQL的RR级别是会对查到的数据行加行共享锁,所以这时候其他事务想删除这些数据行其实是做不到的,所以在RR下,不会出现因delete而出现幻读现象,也就是幻读不包含delete的情况。

MVCC能解决了幻读问题?

网上很多文章会说MVCC或者MVCC+间隙锁解决了幻读问题,实际上MVCC并不能解决幻读问题。如以下的例子:

begin;

#假设users表为空,下面查出来的数据为空

select * from users; #没有加锁

#此时另一个事务提交了,且插入了一条id=1的数据

select * from users; #读快照,查出来的数据为空

update users set name='mysql' where id=1;#update是当前读,所以更新成功,并生成一个更新的快照

select * from users; #读快照,查出来id为1的一条记录,因为MVCC可以查到当前事务生成的快照

commit;
ログイン後にコピー

可以看到前后查出来的数据行不一致,发生了幻读。所以说只有MVCC是不能解决幻读问题的,解决幻读问题靠的是间隙锁。如下:

begin;

#假设users表为空,下面查出来的数据为空

select * from users lock in share mode; #加上共享锁

#此时另一个事务B想提交且插入了一条id=1的数据,由于有间隙锁,所以要等待

select * from users; #读快照,查出来的数据为空

update users set name='mysql' where id=1;#update是当前读,由于不存在数据,不进行更新

select * from users; #读快照,查出来的数据为空

commit;

#事务B提交成功并插入数据
ログイン後にコピー

注意,RR级别下想解决幻读问题,需要我们显式加锁,不然查询的时候还是不会加锁的

原文地址:https://segmentfault.com/a/1190000025156465

作者: X先生

【相关推荐:mysql视频教程

以上がMySQL のトランザクション分離レベルの簡単な分析とその実装原則の説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

phpmyadminを開く方法 phpmyadminを開く方法 Apr 10, 2025 pm 10:51 PM

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

MySQL:世界で最も人気のあるデータベースの紹介 MySQL:世界で最も人気のあるデータベースの紹介 Apr 12, 2025 am 12:18 AM

MySQLはオープンソースのリレーショナルデータベース管理システムであり、主にデータを迅速かつ確実に保存および取得するために使用されます。その実用的な原則には、クライアントリクエスト、クエリ解像度、クエリの実行、返品結果が含まれます。使用法の例には、テーブルの作成、データの挿入とクエリ、および参加操作などの高度な機能が含まれます。一般的なエラーには、SQL構文、データ型、およびアクセス許可、および最適化の提案には、インデックスの使用、最適化されたクエリ、およびテーブルの分割が含まれます。

単一のスレッドレディスの使用方法 単一のスレッドレディスの使用方法 Apr 10, 2025 pm 07:12 PM

Redisは、単一のスレッドアーキテクチャを使用して、高性能、シンプルさ、一貫性を提供します。 I/Oマルチプレックス、イベントループ、ノンブロッキングI/O、共有メモリを使用して同時性を向上させますが、並行性の制限、単一の障害、および書き込み集約型のワークロードには適していません。

MySQLの場所:データベースとプログラミング MySQLの場所:データベースとプログラミング Apr 13, 2025 am 12:18 AM

データベースとプログラミングにおけるMySQLの位置は非常に重要です。これは、さまざまなアプリケーションシナリオで広く使用されているオープンソースのリレーショナルデータベース管理システムです。 1)MySQLは、効率的なデータストレージ、組織、および検索機能を提供し、Web、モバイル、およびエンタープライズレベルのシステムをサポートします。 2)クライアントサーバーアーキテクチャを使用し、複数のストレージエンジンとインデックスの最適化をサポートします。 3)基本的な使用には、テーブルの作成とデータの挿入が含まれ、高度な使用法にはマルチテーブル結合と複雑なクエリが含まれます。 4)SQL構文エラーやパフォーマンスの問題などのよくある質問は、説明コマンドとスロークエリログを介してデバッグできます。 5)パフォーマンス最適化方法には、インデックスの合理的な使用、最適化されたクエリ、およびキャッシュの使用が含まれます。ベストプラクティスには、トランザクションと準備された星の使用が含まれます

なぜMySQLを使用するのですか?利点と利点 なぜMySQLを使用するのですか?利点と利点 Apr 12, 2025 am 12:17 AM

MySQLは、そのパフォーマンス、信頼性、使いやすさ、コミュニティサポートに選択されています。 1.MYSQLは、複数のデータ型と高度なクエリ操作をサポートし、効率的なデータストレージおよび検索機能を提供します。 2.クライアントサーバーアーキテクチャと複数のストレージエンジンを採用して、トランザクションとクエリの最適化をサポートします。 3.使いやすく、さまざまなオペレーティングシステムとプログラミング言語をサポートしています。 4.強力なコミュニティサポートを提供し、豊富なリソースとソリューションを提供します。

Apacheのデータベースに接続する方法 Apacheのデータベースに接続する方法 Apr 13, 2025 pm 01:03 PM

Apacheはデータベースに接続するには、次の手順が必要です。データベースドライバーをインストールします。 web.xmlファイルを構成して、接続プールを作成します。 JDBCデータソースを作成し、接続設定を指定します。 JDBC APIを使用して、接続の取得、ステートメントの作成、バインディングパラメーター、クエリまたは更新の実行、結果の処理など、Javaコードのデータベースにアクセスします。

DockerによるMySQLを開始する方法 DockerによるMySQLを開始する方法 Apr 15, 2025 pm 12:09 PM

DockerでMySQLを起動するプロセスは、次の手順で構成されています。MySQLイメージをプルしてコンテナを作成および起動し、ルートユーザーパスワードを設定し、ポート検証接続をマップしてデータベースを作成し、ユーザーはすべての権限をデータベースに付与します。

Centosはmysqlをインストールします Centosはmysqlをインストールします Apr 14, 2025 pm 08:09 PM

CentOSにMySQLをインストールするには、次の手順が含まれます。適切なMySQL Yumソースの追加。 yumを実行して、mysql-serverコマンドをインストールして、mysqlサーバーをインストールします。ルートユーザーパスワードの設定など、MySQL_SECURE_INSTALLATIONコマンドを使用して、セキュリティ設定を作成します。必要に応じてMySQL構成ファイルをカスタマイズします。 MySQLパラメーターを調整し、パフォーマンスのためにデータベースを最適化します。

See all articles