innodb next-key lock解析_MySQL

Jun 01, 2016 pm 01:03 PM
innodb

参考http://blog.csdn.net/zbszhangbosen/article/details/7434637#reply

这里补充一些:

(1)InnoDB默认加锁方式是next-key locking

(2)在聚集索引中,如果主键有唯一性约束(unique,auto increment),next-key locking 会自动降级为record locking。

(3)由于事务的隔离性和一致性要求,会对所有扫描到的record加锁。比如:update ... where/delete .. where/select ...from...lock in share mode/ select .. from .. for update这都是next-key lock。

(4)注意优化器的选择。包括聚集索引和辅助索引,有时会用全表扫描替代索引扫描,这时整张表(聚集索引表)都会被加锁。

record lock:记录锁,也就是仅仅锁着单独的一行

gap lock:区间锁,仅仅锁住一个区间(注意这里的区间都是开区间,也就是不包括边界值,至于为什么这么定义?innodb官方定义的)
next-key lock:record lock+gap lock,所以next-key lock也就半开半闭区间,且是下界开,上界闭。(为什么这么定义?innodb官方定义的)
下面来举个手册上的例子看什么是next-key lock。假如一个索引的行有10,11,13,20
那么可能的next-key lock的包括:
(无穷小, 10]
(10,11]
(11,13]
(13,20]
(20, 无穷大) (这里无穷大为什么不是闭合?你数学不到家~~)
好了现在通过举例子说明:


表test
mysql> show create table test;
+-------+--------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                           |
+-------+--------------------------------------------------------------------------------------------------------+
| test  | CREATE TABLE `test` (
  `a` int(11) NOT NULL,
  PRIMARY KEY (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 |
+-------+--------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
mysql> select * from test;
+----+
| a  |
+----+
| 11 |
| 12 |
| 13 |
| 14 |
+----+
4 rows in set (0.00 sec)
开始实验:
(一)
session 1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)


mysql> delete from test where a=11;
Query OK, 1 row affected (0.00 sec)


session 2:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values(10);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(15);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(9);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values(16);
Query OK, 1 row affected (0.01 sec)


mysql> rollback;
Query OK, 0 rows affected (0.00 sec)


ok,上面的情况是预期的,因为a上有索引,那么当然就只要锁定一行,所以其他行的插入不会被阻塞。
那么接下来的情况就有意思了
(二)
session 1(跟上一个session 1相同):
delete from test where a=22;
Query OK, 0 rows affected (0.01 sec)
session 2:
mysql> insert into test values (201);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (20);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (19);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (18);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (16);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (9);
Query OK, 1 row affected (0.00 sec)
从上面的结果来看,在a=11后面所有的行,也就是区间(11,无穷大)都被锁定了。先不解释原因,再来看一种情况:
(三)
session 1:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from test;
+----+
| a  |
+----+
|  7 |
|  9 |
| 10 |
| 12 |
| 13 |
| 14 |
| 15 |
| 22 |
| 23 |
| 24 |
| 25 |
+----+
11 rows in set (0.00 sec)


mysql> delete from test where a=21;
Query OK, 0 rows affected (0.00 sec)
session 2:
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> insert into test values (20);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (26);
Query OK, 1 row affected (0.00 sec)
mysql> insert into test values (21);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (16);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> insert into test values (6);
Query OK, 1 row affected (0.01 sec)
从这里可以看出,现在被锁住的区间就只有[16,21)了。
有了前面对三种类型的加锁解释,现在可以来解释为什么会这样了,在innodb表中 delete from where ..针对扫描到的索引记录加next-key锁(具体的什么语句加什么锁可以查看手册,另外需要说明一下,行锁加锁对象永远是索引记录,因为innodb中表即索引) 。
在(一)中,实际上加的next-key lock就是(11,11] 因此也只有a=11这一条记录被锁住,其他所有插入都没有关系。
在(二)中,因为a=22这条记录不存在,而且22比表里所有的记录值都大,所以在innodb看来锁住的区间就是(14, 无穷大)。所以在插入14以后的值都提示被锁住,而14之前的则可以。
在(三)种,a=21也是不存在,但是在表里面21前后都有记录,因此这里next-key lock的区间也就是(15,21],因此不在这个区间内的都可以插入。
那么为什么next-key lock都是下界开区间,上界闭区间呢?这个倒不重要,管它呢,但是有一点我个人却觉得比较怪,比如说
delete test where a > 11           #------- 1
它的next-key lock是(11, 无穷大) 
delete test where a
它的next-key lock是(无穷小, 10]
这样给人的感觉就很怪,因为在手册上对next-key lock的定义:
Next-key lock: This is a combination of a record lock on the index record and a gap lock on the gapbefore the index record.
而在1那种情况下,如果按照手册上的解释,记录锁和它之前的gap那么就会有些牵强。[今天再次看了一遍官方手册,是之前自己的理解不到位,这个before是对的,因为innodb在加锁时是所有扫描过程中遇到的记录都会被加锁,那么对于1那种情况,实际上是从12开始扫描,但是因为要保证a>11的都被delete掉,因此得一直扫描下去那自然最大值就是无穷大,因为这个next-key lock就是无穷大这条记录(这是假设的一条记录,表示一个边界)加上它之前的gap lock (11, 无穷大),所以在任何时候next-lock都是record lock加上这个record之前的一个gap lock]
但是只要我们自己能理解就行了:记录锁---锁单条记录;区间锁---锁一个开区间;next-key 锁---前面两者的结合,而不要管什么before。
另外next-key lock虽然在很多时候是锁一个区间,但要明白一个区间也可能只有一个元素,因此在称delete from tb where key=x 这种情况下加next-key锁也是完全正确的。
另外还提两点:
1.如果我们的SQL语句里面没有利用到索引,那么加锁对象将是所有行(但不是加表锁),所以建索引是很重要的
2.next-key lock是为防止幻读的发生,而只有repeatable-read以及以上隔离级别才能防止幻读,所以在read-committed隔离级别下面没有next-key lock这一说法。
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

MySQL がバイナリ コンテンツから InnoDB 行フォーマットを認識する方法 MySQL がバイナリ コンテンツから InnoDB 行フォーマットを認識する方法 Jun 03, 2023 am 09:55 AM

InnoDB はディスク上のテーブルにデータを保存するストレージ エンジンであるため、シャットダウンして再起動した後でもデータは残ります。データ処理の実際のプロセスはメモリ内で発生するため、ディスク内のデータをメモリにロードする必要があります。書き込みまたは変更要求を処理している場合は、メモリ内の内容もディスクに更新する必要があります。また、ディスクへの読み取りおよび書き込みの速度は非常に遅いことがわかっており、これはメモリ内での読み取りおよび書き込みとは数桁異なります。したがって、テーブルから特定のレコードを取得したい場合、InnoDB ストレージ エンジンは読み取りを行う必要がありますか?ディスクからレコードを 1 つずつ取り出しますか? InnoDB で採用されている方法は、データを複数のページに分割し、ページをディスクとメモリ間の対話の基本単位として使用することです。InnoDB のページのサイズは通常 16 です。

mysql innodbとは何ですか mysql innodbとは何ですか Apr 14, 2023 am 10:19 AM

InnoDB は、MySQL のデータベース エンジンの 1 つです。現在、MySQL のデフォルトのストレージ エンジンであり、MySQL AB によるバイナリ リリースの標準の 1 つです。InnoDB は、二重トラック認証システムを採用しており、1 つは GPL 認証、もう 1 つは独自のソフトウェアです認可。 InnoDB は、トランザクション データベースに推奨されるエンジンであり、トランザクション セキュリティ テーブル (ACID) をサポートしています。InnoDB は、同時実行性を最大限にサポートできる行レベルのロックをサポートしています。行レベルのロックは、ストレージ エンジン層によって実装されます。

MySQL の innoDB でのファントム読み取りを解決する方法 MySQL の innoDB でのファントム読み取りを解決する方法 May 27, 2023 pm 03:34 PM

1. MySQL トランザクション分離レベル これら 4 つの分離レベルでは、複数のトランザクションの同時実行性の競合がある場合、ダーティ リード、非反復読み取り、ファントム読み取りの問題が発生する可能性があり、innoDB は反復可能読み取り分離レベル モードでこれらの問題を解決します。ファントム リーディングの説明、2. ファントム リーディングとは? ファントム リーディングとは、図に示すように、同じトランザクション内で同じ範囲を前後 2 回クエリしたときに得られる結果が矛盾することを意味します。 . この時点では、条件を満たすデータは 1 つだけです。2 番目のトランザクションでは、データの行を挿入して送信します。最初のトランザクションが再度クエリを実行すると、取得される結果は、前のトランザクションの結果より 1 つ多くなります。最初のクエリ。データ。最初のトランザクションの最初と 2 番目のクエリは両方とも同じであることに注意してください

mysql innodb例外を処理する方法 mysql innodb例外を処理する方法 Apr 17, 2023 pm 09:01 PM

1. mysql をロールバックして再インストールします。このデータを他の場所からインポートする手間を避けるために、まず現在のライブラリ (/var/lib/mysql/location) のデータベース ファイルのバックアップを作成します。次に、Perconaserver 5.7 パッケージをアンインストールし、元の 5.1.71 パッケージを再インストールし、mysql サービスを開始すると、Unknown/unsupportedtabletype:innodb というプロンプトが表示され、正常に開始できませんでした。 11050912:04:27InnoDB:バッファプールの初期化中、サイズ=384.0M11050912:04:27InnoDB:完了

MySQL ストレージ エンジンの選択の比較: InnoDB、MyISAM、およびメモリのパフォーマンス インデックスの評価 MySQL ストレージ エンジンの選択の比較: InnoDB、MyISAM、およびメモリのパフォーマンス インデックスの評価 Jul 26, 2023 am 11:25 AM

MySQL ストレージ エンジンの選択の比較: InnoDB、MyISAM、およびメモリのパフォーマンス インデックスの評価 はじめに: MySQL データベースでは、ストレージ エンジンの選択がシステム パフォーマンスとデータの整合性において重要な役割を果たします。 MySQL はさまざまなストレージ エンジンを提供します。最も一般的に使用されるエンジンには、InnoDB、MyISAM、Memory などがあります。この記事では、これら 3 つのストレージ エンジンのパフォーマンス指標を評価し、コード例を通じて比較します。 1. InnoDB エンジン InnoDB は私のものです

MyISAM および InnoDB ストレージ エンジンを使用して MySQL のパフォーマンスを最適化する方法 MyISAM および InnoDB ストレージ エンジンを使用して MySQL のパフォーマンスを最適化する方法 May 11, 2023 pm 06:51 PM

MySQL は広く使用されているデータベース管理システムであり、ストレージ エンジンが異なればデータベースのパフォーマンスに与える影響も異なります。 MyISAM と InnoDB は、MySQL で最もよく使用される 2 つのストレージ エンジンですが、これらには異なる特性があり、不適切に使用するとデータベースのパフォーマンスに影響を与える可能性があります。この記事では、これら 2 つのストレージ エンジンを使用して MySQL のパフォーマンスを最適化する方法を紹介します。 1. MyISAM ストレージ エンジン MyISAM は、MySQL で最も一般的に使用されるストレージ エンジンであり、その利点は高速であり、ストレージ スペースが小さいことです。 MyISA

MySQL ストレージ エンジンの読み取りパフォーマンスを向上させるためのヒントと戦略: MyISAM と InnoDB の比較分析 MySQL ストレージ エンジンの読み取りパフォーマンスを向上させるためのヒントと戦略: MyISAM と InnoDB の比較分析 Jul 26, 2023 am 10:01 AM

MySQL ストレージ エンジンの読み取りパフォーマンスを向上させるためのヒントと戦略: MyISAM と InnoDB の比較分析 はじめに: MySQL は、最も一般的に使用されているオープン ソース リレーショナル データベース管理システムの 1 つで、主に大量の構造化データの保存と管理に使用されます。ほとんどのアプリケーションでは読み取り操作が主な操作であるため、アプリケーションではデータベースの読み取りパフォーマンスが非常に重要になることがよくあります。この記事では、MySQL ストレージ エンジンの読み取りパフォーマンスを向上させる方法に焦点を当て、一般的に使用される 2 つのストレージ エンジンである MyISAM と InnoDB の比較分析に焦点を当てます。

GIS データをサポートする MySQL ストレージ エンジン: InnoDB での空間インデックスの最適化 GIS データをサポートする MySQL ストレージ エンジン: InnoDB での空間インデックスの最適化 Jul 24, 2023 pm 11:07 PM

GIS データをサポートする MySQL ストレージ エンジン: InnoDB における空間インデックスの最適化 要約: 最新のデータベース アプリケーションでは、地理情報システム (GIS) データがますます重要な役割を果たしています。 GIS データ処理は複雑かつ動的であり、従来のリレーショナル データベースはこの種のデータの処理が苦手です。ただし、MySQL は、GIS データの処理を最適化できるストレージ エンジン InnoDB を提供します。この記事では、InnoDB ストレージ エンジンで空間インデックスを使用して GIS データを最適化する方法を紹介します。

See all articles