天天看點

MySQL加非聚簇索引造成core dump及簡單分析

本文從5.1.48下的一個bug說起。前提是新特性fast index creation.

1、現象

5.1.48 (innodb plugin 1.0.9)

session1

session2

create table tb(a int)engine=innodb;

insert into tb values(1),(2),(3),(4),(5);

begin;

select * from tb where a=3;

a

3

alter table tb add index a(a);

error 2013 (hy000): lost connection to mysql server during query

說明:session1提示lost connection,實際上mysql已經dump了。

2、分析

這個結果還是比較好了解的。有fast index creation,預設不需要重作表,是以沒有表鎖。

session1開始于加索引之前,第一個select語句使用的是全表掃描,第二個select語句執行時,索引已經建好,是以查詢時候使用索引a。這在實作上就可能觸發諸多雷區(實際上概念上都已經錯誤,下文描述)。

在這個版本的實作中,由于建立索引導緻第二次select時候使用了prebuilt-> search_tuple. 這個結構在事務開始前沒有初始化,是以在嘗試使用時類型判斷錯誤直接abort。(row0sel.c)

3、最新版本的實作

由于5.1.48在我們線上用的比較普遍,是以特别查了這個版本的實作和原因。在5.1最新版本中已經避免了這個問題;5.5最新版本也避免了,但有趣的是,兩個版本的實作機制完全不同。

我們先列出兩個版本的效果再讨論。

5.1.61的效果

5.1.61 (innodb plugin 1.0.17)

error 1412 (hy000): table definition has changed, please retry transaction

5.5.19的效果

5.5.19

lock here

可以看到,兩個版本的實作方法不同。5.1裡面通過判斷索引生成時間與事務開始時間的差别,提示使用者需要重新開機事務。

5.5則是作了個鎖更新,鎖住加索引操作。并且這個操作不影響session1的一緻性讀。(當然很容易想到在session1執行一個更新操作是什麼效果)。

政策上5.5的實作更符合repeatable-read的概念。

4、其他

說明下,5.1的其他版本未試驗。

繼續閱讀