日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長提供免費收錄網(wǎng)站服務,提交前請做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:52000
  • 待審:37
  • 小程序:12
  • 文章:1037587
  • 會員:756

對于5.7.23之前的版本在評估類似DDL操作的時候需要謹慎,可能評估為瞬間操作,但是實際上線的時候跑了很久,這個就容易導致超過維護窗口,甚至更大的故障。

一、問題模擬

使用5.7.22版本:

建表語句,注意這里字段a包含了一個索引,這是觸發(fā)這個BUG的必要條件:
MySQL> show create table testmy G
*************************** 1. row ***************************
       Table: testmy
Create Table: CREATE TABLE `testmy` (
  `id` int(11) DEFAULT NULL,
  `a` varchar(24) DEFAULT NULL COMMENT 'test1',
  KEY `a` (`a`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

數(shù)據(jù)量:
mysql> select count(*) from testmy;
+----------+
| count(*) |
+----------+
|   262144 |
+----------+
1 row in set (5.17 sec)

執(zhí)行DDL語句:
alter table testmy modify `a` varchar(30) comment 'test1111';

本DDL語句主要完成:

  • 擴展varchar從24*4到30*4
  • 更改字段的comment

按照常理來講這個DDL是只修改元數(shù)據(jù)的,因此應該瞬間完成,但是實際在5.7.22版本中這個語句重建了索引a,耗時如下:

mysql> alter table testmy modify `a` varchar(30) comment 'test1';
Query OK, 0 rows affected (2.50 sec)
Records: 0  Duplicates: 0  Warnings: 0

很明顯重建了索引,才會有這么高的耗時。而在5.7的新版本或者8.0中測試這個語句是瞬間完成的。

二、官方文檔說明

也就是說正常的擴展varchar的長度,只要字符集字節(jié)數(shù)量*字符數(shù)量不跨越256,那么就是修改元數(shù)據(jù),不會重建索引。

三、問題分析

既然不符合官方文檔的說明,那么這個問題肯定是某種BUG導致。當我們進行DDL操作的時候,需要對比更改部分和現(xiàn)有的數(shù)據(jù)字典中標定義的差別,然后根據(jù)這些差別來定義操作方式,然后根據(jù)操作方式來判斷哪一種DDL 方式比較合適,關于定義操作方式的部分來自于函數(shù)fill_alter_inplace_info,而在函數(shù)中會根據(jù)新表的索引和老表的索引字段的長度判斷是否需要drop索引和新建索引,代碼中體現(xiàn)為如下:

  /*
    Step through all keys of the old table and search matching new keys.
  */
  for (table_key= table->key_info; table_key < table_key_end; table_key++) //循環(huán)老表的索引
  {
    /* Skip renamed keys. */
    if (table_key->flags & HA_KEY_RENAMED)
      continue;

    new_key= find_key_cs(table_key->name, ha_alter_info->key_info_buffer,
                         new_key_end);//在新的定義中是否包含這個索引

    if (new_key == NULL) //如果找不到說明這個索引要drop掉
    {
      /* Matching new key not found. This means the key should be dropped. */
      ha_alter_info->add_dropped_key(table_key); //加入到drop key buffer
    }
    else if (has_index_def_changed(ha_alter_info, table_key, new_key))//是否索引有所改變
    {
      /* Key was modified. */
      ha_alter_info->add_modified_key(table_key, new_key); //加入到modify key buffer
    }
  }

而加入到modify buffer后這個索引就是需要drop并且add的,因此DDL類型定義為,Alter_inplace_info::DROP_INDEX|Alter_inplace_info::ADD_INDEX,因此就需要進行索引的刪除和重建,因此關鍵就是函數(shù)has_index_def_changed的更改,我們先看5.7.22的這個BUG相關的判斷點:

    if (key_part->length != new_part->length)
      return true;  

也就是當索引字段長度更改了就返回true。而在新版本中:

    if (key_part->length != new_part->length &&
        ha_alter_info->alter_info->flags == Alter_info::ALTER_CHANGE_COLUMN &&
        (key_part->field->is_equal((Create_field *)new_field) == IS_EQUAL_PACK_LENGTH))
    {
      ha_alter_info->handler_flags|=
          Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH;
    }
    else if (key_part->length != new_part->length)
      return true;

變更還是比較大的,主要是key_part->field->is_equal((Create_field *)new_field) == IS_EQUAL_PACK_LENGTH)這個條件是否滿足,而判定的函數(shù)為Field_varstring::is_equal,

uint Field_varstring::is_equal(Create_field *new_field)
{
  if (new_field->sql_type == real_type() &&
      new_field->charset == field_charset)
  {
    if (new_field->length == max_display_length()) //新老字段長度相同
      return IS_EQUAL_YES;
    DBUG_ASSERT(0 == (new_field->length % field_charset->mbmaxlen));
    DBUG_ASSERT(0 == (max_display_length() % field_charset->mbmaxlen));
    if (new_field->length > max_display_length() && //新字段長度大于老字段長度,需要額外判斷
 ((new_field->length <= 255 && max_display_length() <= 255) ||
  (new_field->length > 255 && max_display_length() > 255)))
      return IS_EQUAL_PACK_LENGTH; // VARCHAR, longer variable length
  }
  return IS_EQUAL_NO;
}

其重點為如下:

  • A:如果新的字段長度>老的字段的長度
  • B:字段長度不能跨越255字節(jié)

那么則返回IS_EQUAL_PACK_LENGTH,因此就這個點上has_index_def_changed函數(shù)就會返回false,不會刪除和重建索引了。

四、相關BUG

這個BUG雖然有點老了,是5.7.23修復的,如下:

但是對于5.7.23之前的版本在評估類似DDL操作的時候需要謹慎,可能評估為瞬間操作,但是實際上線的時候跑了很久,這個就容易導致超過維護窗口,甚至更大的故障,因此還是建議任何DDL操作除了翻看官方文檔以外,都需要在相同版本的數(shù)據(jù)庫測試環(huán)境測試其耗時是否達到預估水平。

分享到:
標簽:MySQL
用戶無頭像

網(wǎng)友整理

注冊時間:

網(wǎng)站:5 個   小程序:0 個  文章:12 篇

  • 52000

    網(wǎng)站

  • 12

    小程序

  • 1037587

    文章

  • 756

    會員

趕快注冊賬號,推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨大挑戰(zhàn)2018-06-03

數(shù)獨一種數(shù)學游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數(shù)有氧達人2018-06-03

記錄運動步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定