MySQL淺談(索引、鎖)

1. MySQL引擎

mysql> show engines;
複製代碼
Engine Support Comment Transactions XA Savepoints
InnoDB DEFAULT Supports transactions, row-level locking, and foreign keys YES YES YES
MRG_MYISAM YES Collection of identical MyISAM tables NO NO NO
MEMORY YES Hash based, stored in memory, useful for temporary tables NO NO NO
BLACKHOLE YES /dev/null storage engine (anything you write to it disappears) NO NO NO
MyISAM YES MyISAM storage engine NO NO NO
CSV YES CSV storage engine NO NO NO
ARCHIVE YES Archive storage engine NO NO NO
PERFORMANCE_SCHEMA YES Performance Schema NO NO NO
FEDERATED NO Federated MySQL storage engine NULL NULL NULL

其餘引擎詳情請移步:dev.mysql.com/doc/refman/…html

InnoDB: The default storage engine in MySQL 5.7. InnoDB is a transaction-safe (ACID compliant) storage engine for MySQL that has commit, rollback, and crash-recovery capabilities to protect user data. InnoDB row-level locking (without escalation to coarser granularity locks) and Oracle-style consistent nonlocking reads increase multi-user concurrency and performance. InnoDB stores user data in clustered indexes to reduce I/O for common queries based on primary keys. To maintain data integrity, InnoDB also supports FOREIGN KEY referential-integrity constraints. For more information about InnoDB, see Chapter 14, The InnoDB Storage Engine.mysql

  • 翻譯:

innodb: mysql 5.7 中的默認存儲引擎。innodb 是 mysql 的事務安全 (符合 acid) 存儲引擎, 具備提交、回滾和崩潰恢復功能, 可保護用戶數據。innodb 行級鎖定 (不升級到更粗粒度鎖) 和 oracle 類型一導致用非鎖定讀取,可提升多用戶併發性和性能。innodb 將用戶數據存儲在彙集索引中, 以減小基於主鍵的常見查詢的 I/O。爲了保持數據完整性, innodb 還支持外鍵。有關 innodb 的詳細信息, 請參閱第14章, inodb 存儲引擎。算法

InnoDB存儲數據結構 - B+Tree

  • 爲何使用B+Tree?
    索引的常見模型常見的有,哈希表、有序數組、搜索樹。
    有序數組,優勢是等值查詢,範圍查詢都很是快,缺點也很明顯,就是插入效率過低,由於若是從中間插入,要移動後面全部的元素。

Hash Index Characteristics(哈希索引特性)

Hash indexes have somewhat different characteristics from those just discussed:
They are used only for equality comparisons that use the = or <=> operators (but are very fast). They are not used for comparison operators such as < that find a range of values. Systems that rely on this type of single-value lookup are known as 「key-value stores」; to use MySQL for such applications, use hash indexes wherever possible.sql

哈希結構只適用於等值查詢(但這樣速度很是快)。哈希結構不支持順序檢索例如'<'、'>'、"between and"等,這種存儲結構屬於「鍵值」查詢,符合這種需求能夠考慮使用哈希索引。數據庫

The optimizer cannot use a hash index to speed up ORDER BY operations. (This type of index cannot be used to search for the next entry in order.)express

優化器不能使用哈希索引來加快 order by 操做。(此類型的索引不能用於按順序搜索下一個條目。數組

MySQL cannot determine approximately how many rows there are between two values (this is used by the range optimizer to decide which index to use). This may affect some queries if you change a MyISAM or InnoDB table to a hash-indexed MEMORY table.安全

mysql 不能大體肯定兩個值之間有多少行 (範圍優化器使用它來決定要使用哪一個索引)。若是將 MyISAM 或 InnoDB 表更改成哈希索引的內存表, 這可能會影響某些查詢。bash

  • Only whole keys can be used to search for a row. (With a B-tree index, any leftmost prefix of the key can be used to find rows.)

只有等值匹配才能適用哈希結構查詢某一行。(而適用B-tree索引,最左前綴就能夠用於查詢。) 哈希表,優勢就是查詢快,缺點是範圍查詢效率很低(由於無序)。適用於等值查詢。數據結構

B-Tree Index Characteristics(B樹索引特性)

A B-tree index can be used for column comparisons in expressions that use the =, >, >=, <, <=, or BETWEEN operators. The index also can be used for LIKE comparisons if the argument to LIKE is a constant string that does not start with a wildcard character.

一個B樹索引能夠適用於=、>、>=、<、<=、BETWEEN 等操做符。B樹索引也能夠用於LIKE比較,只有當LIKE的參數是一個字符串常量而且不以通配符開始才能夠適用索引。 樹結構,優勢有序,而且多叉樹能夠減小磁盤I/O次數。

  • B-Tree和B+Tree。

首先,B-Tree讀B樹,而不讀B減樹。從上圖能夠看出B樹可能沒有遍歷到葉子節點就命中目標,而B+樹每一個父節點都會出如今子節點中(如圖中的10和15兩個節點,也都會在葉子節點中出現)。另外B-Tree和B+Tree的衛星數據儲存位置不一樣。

衛星數據:指索引元素所指向的數據記錄。例如數據庫中的某一行數據。

B-Tree中不管中間節點仍是葉子節點都帶有衛星數據。而B+Tree只有葉子節點帶有衛星數據,中間節點只帶有索引。以下圖所示: B-Tree的結構和B+Tree結構相似,只是非葉子節點也會存儲數據,而B+Tree只在葉子節點存儲數據,雖然B-Tree可能在遍歷到第二層時就能夠獲得數據返回,可是因爲非葉子節點也會存儲數據,致使每一個數據頁存儲的索引更少,致使樹的高度會很高,若是須要遍歷的數據在葉子節點,則很是費時,因此查詢性能不如B+Tree穩定。MySQL,InnoDB引擎一個數據頁大小爲16KB,因此從理論上講,一個數據頁存儲的有用信息越多,樹的高度就會越低,I/O次數越少,搜索效率越高。

InnoDB索引模型

CREATE TABLE `r` (
  `id` int NOT NULL primary key auto_increment,
  `k` int not null,
  `name` varchar(16),
   index(k)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
複製代碼

在表中插入(1,10,"張三"),(2,20,"李四"),(3,30,"王五")。則索引以下圖

主鍵索引的葉子節點存的是整行數據,非主鍵索引的葉子節點存的主鍵的值。
在InnoDB裏,主鍵索引被稱爲聚簇索引或彙集索引(clustered index),非主鍵索引被稱爲二級索引或輔助索引(secondary index)。 在InnoDB中,表都是根據主鍵順序以索引的形式存放的,這種存儲方式的表成爲索引組織表。每個索引在InnoDB裏對應一棵B+樹,數據是有序排列的。 聚簇索引生成規則:

  1. When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. Define a primary key for each table that you create. If there is no logical unique and non-null column or set of columns, add a new auto-increment column, whose values are filled in automatically.

定義主鍵用主鍵做爲聚簇索引。

  1. If you do not define a PRIMARY KEY for your table, MySQL locates the first UNIQUE index where all the key columns are NOT NULL and InnoDB uses it as the clustered index.

沒定義主鍵使用第一個惟一非空索引做爲聚簇索引。

  1. If the table has no PRIMARY KEY or suitable UNIQUE index, InnoDB internally generates a hidden clustered index named GEN_CLUST_INDEX on a synthetic column containing row ID values. The rows are ordered by the ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order.

沒定義主鍵,也沒定義惟一索引,生成一個隱藏的列做爲聚簇索引。
更多詳情

基於主鍵索引和普通索引查詢有什麼區別?

  1. 若是sql是 select * from r where id = 1; 即經過主鍵方式查詢,只須要搜索主鍵這棵B+樹。
  2. 若是sql是 select * from r where k = 10; 即經過普通索引查詢,須要先搜索普通索引k這棵B+樹,拿到主鍵id=1,在用id=1再去搜索主鍵索引的B+樹。這個過程叫作回表

在分析一個sql語句:select * from r where k between 8 and 22;

  1. 在k索引樹上找到k=10的記錄,取得id=1;
  2. 在id索引樹上找到id=1的對應的行記錄data(回表);
  3. 在k索引樹上找到k=20的記錄,取得id=2;
  4. 在id索引樹上找到id=2的對應的行記錄data(回表);
  5. 在k索引樹取下一個值k=30,不知足,循環結束。

這個例子因爲要查詢的結果只有主鍵索引上面纔有,因此不得不回表。那麼如何避免回表?

覆蓋索引

若是sql語句是:select id from r where k between 8 and 22,因爲這時只須要查詢id值,而id值已經在k索引樹上了,因此不須要回表查詢,索引k已經覆蓋了咱們的查詢需求,稱之爲覆蓋索引。
因爲覆蓋索引能夠減小數的搜索次數,顯著提升查詢性能,因此使用覆蓋索引是一個經常使用的優化手段。
場景:假設有一個市民表:

CREATE TABLE `citizen` (
  `id` int(11) NOT NULL,
  `id_card` varchar(32) DEFAULT NULL,
  `name` varchar(32) DEFAULT NULL,
  `age` int(11) DEFAULT NULL,
  `ismale` tinyint(1) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `id_card` (`id_card`),
  KEY `name_age` (`name`,`age`)
) ENGINE=InnoDB
複製代碼

是否有必要建立身份證號和姓名的聯合索引?
根據業務來看,若是有根據身份證號查詢姓名的高頻需求,能夠考慮建立身份證號和姓名的聯合索引,避免回表提升查詢的效率。

最左前綴原則

select * from citizen where name = "張三" ;
複製代碼

這個確定是能夠用name索引的,若是要查詢姓張的人,語句是

select * from citizen where name like '張%';
複製代碼

這時也能夠用上name的索引,查找到第一個以張開頭的人,向後遍歷直到不知足條件爲止。
而若是要檢索姓張,年齡10歲的男孩。

select * from tuser where name like '張%' and age=10 and ismale=1;
複製代碼

這個在MySQL5.6之前是要根據查詢到姓張的人開始一個一個回表去查詢age是否知足10的,而5.6引入了索引下推優化(index condition pushdown),能夠在遍歷中,對索引中包含的字段先判斷,過濾掉不知足的記錄,減小回表次數。 如下兩句可使用到索引。

1. SELECT * FROM tbl_name WHERE key_col LIKE 'Patrick%';
2. SELECT * FROM tbl_name WHERE key_col LIKE 'Pat%_ck%';
複製代碼

第一句只有'Patrick' <= key_col < 'Patricl'的行纔會被篩選出來,而第二句只有'Pat' <= key_col < 'Pau' 會被篩選出來。
如下兩句不會使用索引:

3. SELECT * FROM tbl_name WHERE key_col LIKE '%Patrick%';
4. SELECT * FROM tbl_name WHERE key_col LIKE other_col;
複製代碼

第三句因爲以通配符開始,不符合最左前綴原則,因此不能適用索引。第四句,因爲LIKE的參數不是一個字符串常量,因此也不使用索引。
若是用 LIKE '%string%' 字符串長度超過3,會使用串匹配的BM算法提升查詢效率。
另外,若是某一列有索引,若是值爲空,使用where col_name IS NULL也是能夠走索引的。

若是業務知足某字段惟一,是否能夠考慮用該字段做爲主鍵?

例如居民身份證號能夠保證惟一,那麼是否用身份證號當作主鍵建表?這裏並太建議,根據上面介紹的聚簇索引和二級索引的結構以後,能夠看出主鍵索引越長對於輔助索引創建須要更多的空間,另外對於聚簇索引,若是索引過長會致使主鍵索引樹的高度變高,由於一個數據頁默認是16k,主鍵索引越長則一個數據頁能容納的索引則越少。身份證號是18位,用字符串來存須要18個字節,而若是使用自增的long來作主鍵,則只有8個字節。另外一個好處就是自增主鍵能夠保證插入只須要插入到數據頁的隊尾,不須要插入中間,而身份證號按照順序排序有可能會插入中間位置,這樣會致使數據頁存滿,數據頁分裂等消耗。

字符串應該如何建立索引?

場景一,根據郵箱登陸是一個廣泛場景,若是郵箱不加索引則須要權標掃描,而若是加入全量索引則須要佔用很大的空間。因爲字符串索引支持最左前綴原則,則咱們能夠這樣建立索引:

alter table user add index index(email(5));
複製代碼

這裏設置email的最左前5個字符做爲索引能夠縮小範圍,可是若是前5個字符可能重複的數據不少,好比zhangsan@XX.com、zhangsi@XX.com、zhangwu@XX.com、zhangliu@XX.com、zhangqi@XX.com都會搜索出來在遍歷,區別度過小,在某字段簡歷索引的一個原則就是這個字段的區別度,如此創建索引區別度過小。因此應該取得區別度可接受的最左前綴。

select count(distinct email) as L from user;(查詢總數)
複製代碼

而後執行下列語句,來看每一個前綴長度索引的區別度,找一個可以接受的長度,好比你的要求是區別度大於95%,那麼能夠算一下多長的前綴符合你的要求,區別度=L(n)/L。

select
count(distinct left(email,4) as L4,
count(distinct left(email,5) as L5,
count(distinct left(email,6) as L6,
count(distinct left(email,7) as L7,
from user;
複製代碼
  • 場景二,仍是身份證的場景,根據身份證進行等值查詢,應該如何創建索引? 提供兩種方案:
  1. 由於身份證前面都是省市生日等重複較多的信息,因此這裏能夠考慮倒序存儲,並選擇一個長度,好比倒數8位做爲前綴索引。
select field_list from t where id_card = reverse('input_id_card_string');
複製代碼
  1. 第二種是用hash,在建立一個身份證hash字段,用這個字段做爲索引。
alter table t add id_card_crc int unsigned, add index(id_card_crc);
複製代碼

查詢時候用如下語句:

select field_list from t where id_card_crc=crc32('input_id_card_string') and id_card='input_id_card_string');
複製代碼

這樣能夠先快速縮小結果集的範圍,在根據結果集遍從來查詢精確的身份證號,提升效率。
缺點:以上幾種方式都不支持範圍查詢,能夠本身根據業務場景本身選擇合適的方式。

隔離級別

未提交讀(READ UNCOMMITTED)

讀未提交是指,一個事務還沒提交時,它作的變動就能被別的事務看到。

提交讀(READ COMMITTED)

讀提交是指,一個事務提交以後,它作的變動纔會被其餘事務看到。

可重複讀(REPEATABLE READ)

可重複讀是指,一個事務執行過程當中看到的數據,老是跟這個事務在啓動時看到的數據是一致的。

串行化(SERIALIZABLE)

串行化,顧名思義是對於同一行記錄,「寫」會加「寫鎖」,"讀」會加「讀鎖」。當出現讀寫鎖衝突的時候,後訪問的事務必須等前一個事務執行完成,才能繼續執行。

  1. 髒讀(dirty read)

讀取到其餘事物未提交的結果。

  1. 虛讀(non-repeatable read)

在事物中無讀到其餘事物提交的UPDATE更新結果。

  1. 幻讀(phantom read)

在事物中無讀到其餘事物提交的INSERT更新結果。

MySQL默認級別是可重複讀,Oracel默認級別是提交讀。

快照讀和當前讀

  • 先看如下場景。在MySQL5.7版本下,默認隔離級別RR下,下面語句的執行結果是什麼?
CREATE TABLE `r` (
  `id` int NOT NULL primary key auto_increment,
  `v` int not null
  ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  
  insert into r values (1,1);
  
複製代碼
  1. 場景一:
事物A 事物B
begin;
1, select * from r; begin;
update r set v=v+1 where id =1;
commit;
2, select * from r;
3, select * from r for update;
commit;

其中1,2,3句id等於3的列 v的值都等於多少?

  1. 場景二:
    先恢復數值,
update r set v = 1 where id =1;
複製代碼
事物A 事物B
begin;
1, select * from r; begin;
update r set v=v+1 where id = 1;
commit;
2, select * from r;
update r set v=v+1 where id = 1;
3, select * from r;
commit;

此時語句一、二、3查詢結果中v的值是多少?

  • 快照讀

簡單的select操做,屬於快照讀,不加鎖。

select * from table where ?;
複製代碼
  • 當前讀

特殊的讀操做,插入/更新/刪除操做,屬於當前讀,須要加鎖。

select * from table where ? lock in share mode;
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;
複製代碼

全部以上的語句,都屬於當前讀,讀取記錄的最新版本。而且,讀取以後,還須要保證其餘併發事務不能修改當前記錄,對讀取記錄加鎖。其中,除了第一條語句,對讀取記錄加S鎖 (共享鎖)外,其餘的操做,都加的是X鎖 (排它鎖)。
爲何併發讀不須要加鎖?
MVCC(參考高性能MySQL)
這裏簡單介紹一下MVCC(多版本併發控制),MVCC的實現是經過保存數據在某個時間點的快照來實現的。不一樣存儲引擎實現的方式也不一樣。這裏簡單介紹一下InnoDB簡化版行爲來講明MVCC是如何工做的。
InnoDB的MVCC是經過在每行記錄後面保存的兩個隱藏列來實現的。兩個列一個保存了行的建立時間,另個一保存了行的過時時間。這裏其實保存的並非具體時間,而是系統版本號(system version number)。每新開啓一個事物,系統版本號都會自動遞增,事物開始時刻的系統版本號會做爲事物的版本號,用來和查詢到的每行記錄版本做爲比較。
下面看下InnoDB, REPEATABLE READ隔離級別下MVCC是如何操做的。

  1. SELECT

a.查詢版本號早於或等於當前事物版本的行數據。這樣能夠保證讀取到的行,要麼早於該事物已經存在,要麼是本事物本身提交的。
b.行的刪除版本要麼未定義,要麼大於當前事物的版本號。這樣能夠保證,當前事物讀取到的行在事物開始以前是未被刪除的。

  1. INSERT

爲新插入的每一行數據保存當前系統版本號做爲行版本號。

  1. DELETE

爲刪除的每一行保存當前系統版本號做爲行刪除標誌。

  1. UPDATE

a. 插入一行數據,保存當前系統版本號做爲行版本號。 b. 同時添加當前的系統版本號做爲原數據的刪除標記。

InnoDB-鎖

共享鎖和排他鎖

  • 共享鎖、讀鎖(Shared (S) Lock)

持有行記錄讀鎖的事物容許讀取該行記錄。

  • 排他鎖、寫鎖( Exclusive (X) Lock)

持有行記錄寫鎖的事物容許更新活刪除該行記錄。

表鎖

行鎖(Record Locks)

A record lock is a lock on an index record. For example, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; prevents any other transaction from inserting, updating, or deleting rows where the value of t.c1 is 10.

行鎖是做用在索引記錄上的。例如, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;會防止其餘事物對於t.c1=10的增、刪、改。

Record locks always lock index records, even if a table is defined with no indexes. For such cases, InnoDB creates a hidden clustered index and uses this index for record locking.

行鎖老是鎖索引記錄的,儘管沒有建立索引,對於沒有建立索引的狀況,InnoDB建立一個隱藏的聚簇索引並用該索引來實現行鎖。

間隙鎖(Gap Locks)

A gap lock is a lock on a gap between index records, or a lock on the gap before the first or after the last index record.

間隙鎖是做用於索引記錄之間或第一條索引記錄以前或最後一條索引記錄以後的鎖。

Gap locking is not needed for statements that lock rows using a unique index to search for a unique row.

間隙鎖不會做用於使用惟一索引去檢索惟一行記錄的狀況。

爲何會有間隙鎖?

防止幻讀。(當前讀)

  • 下面這個語句加什麼鎖?已知條件MySQL5.7版本,InnoDB引擎,隔離級別RR。
delete from t where id = 10;
複製代碼

對id = 10的記錄加寫鎖 (走主鍵索引)。這個答案對嗎?
多是對的也有多是錯的,由於已知條件不足。缺乏下列條件:
1,id是不是主鍵?
2,id列若是不是主鍵,那麼id上是否有索引?
3,id列上若是有二級索引,那麼這個索引是不是惟一索引?
4,id=10的記錄是否存在?
根據如下組合來判斷加的鎖:

  1. id列是主鍵,只對id = 10 的記錄加X鎖。
  2. id是惟一索引,而且id = 10 記錄存在,對惟一索引id的B+Tree id = 10 的記錄加行鎖,同時對聚簇索引(主鍵索引)上對應id = 10 的主鍵 b 加X鎖。
  3. id是惟一索引,可是id = 10 的記錄不存在,對惟一索引id的B+Tree id = 10 的空隙加就間隙鎖,防止新的符合條件的記錄插入,產生幻讀,即鎖住id索引樹(8,b)至(15,c)之間的空間。

4. id非惟一索引,首先對id的索引樹符合id = 10的記錄加X鎖,而且對符合id = 10對應的主鍵索引記錄加X鎖,還要對id索引樹可能插入id = 10 的位置加入間隙鎖,也就是(6,a)至(10,b), (10,b)至(10,c), (10,c)至(17,d)。

5. id無索引,這種是最恐怖的狀況,對主鍵索引全部行記錄加X鎖,全部空隙加間隙鎖,儘管MySQL對此有些優化,也不建議這樣的方式,尤爲是長事物,會使除了快照讀的全部業務停擺。

看下面幾個例子:

CREATE TABLE `t` (
  `id` int(11) NOT NULL,
  `k` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_k` (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
複製代碼
insert into t values(2,2),(6,6);
複製代碼

MySQL5.7版本,InnoDB引擎,隔離級別是RR狀況下,建立表t,其中id是主鍵,k是普通索引。

問題1:其中語句 一、二、3能夠插入嗎?

事物A 事物B 事物C 事物D
begin;
select * from t where k=4 for update;
1, insert into t values (3,3);
2, insert into t values (4,4);
3, insert into t values (5,5);
commit;

是不能插入的,由於k是普通索引,因此會在索引 k 的B+樹上 k=2 至 k=6 之間加上間隙鎖,防止幻讀。

問題2:其中語句 四、五、六、 7能夠插入嗎?

事物A 事物B 事物C 事物D 事物E
begin;
select * from t where k=4 for update;
4, insert into t values (1,2);
5, insert into t values (3,2);
6, insert into t values (5,6);
7, insert into t values (7,6);
commit;

其中語句 4, 7 是能夠插入的,而語句 5, 6 是不能插入的。

根據前面的加鎖機制分析一下緣由:
首先,select * from t where k=4 for update,因爲 k 是普通索引,因此在InnoDB引擎下,默認隔離級別RR狀況下會加間隙鎖防止新數據插入,防止幻讀。加鎖方式以下圖:

若是4, 5, 6, 7語句能夠插入的話應該插入在什麼位置呢?
請看下圖:

因爲B+樹索引有序排列,因此若是四、五、六、7都可以插入,位置應該插入普通索引k的B+Tree,如上圖所示。從上圖插入數據的位置就能夠很明顯的看出爲何語句五、6不能插入了。由於對於K索引樹來講葉子節點存的是(k, id),除了要按k值排序,也要按照id排序,因此insert into t values (3,2)和insert into t values (5,6)插入的位置就落在了間隙鎖的範圍,因此是不能插入的,而insert into t values (1,2)和insert into t values (7,6)插入的位置落在間隙鎖範圍以外,因此能夠插入。

  • 間隙鎖到底鎖的是什麼? 經過上面這個例子能夠看出,其實間隙鎖並無徹底鎖住k=2和k=6記錄的插入,也就是鎖住的不是具體的值,而是全部可能插入新值k=4的位置,在本例中也就是(2,2)至(6,6)之間的位置,由於索引是有序排列的,因此k=4只能插入(2,2)至(6,6)之間。

  • 什麼狀況下產生間隙鎖?

  1. where條件後用非索引列約束的時候。
  2. where後用非惟一索引列約束(等值搜索、字符串的最左前綴 LIKE '張%' )的時候。
  3. where條件後用惟一索引、普通索引作範圍查詢時候( <、<=、>、>=、between and )。
  4. 對於多列聯合惟一索引,若是查詢沒有包含全部列的等值查詢也會產生間隙鎖。例如,聯合惟一索引column_一、cloumn_二、column_3的聯合惟一索引,若是當前讀語句是 ··· where column_1 = value_1 and cloumn_2 = value_2,則會產生間隙鎖,由於沒有包含column_3。
  5. 根據惟一索引deleteupdateselect ··· lock in share modeselect ··· for update等值條件約束不存在的列的時候。

死鎖問題

相關文章
相關標籤/搜索