mysql有table函数吗_mysql_alter_table函数流程的部分修改和注解
change log
gdb info
set args --defaults-file=etc/my.cnf --user=liuzhuan
調試的斷點列表
mysql_alter_table()
create_table_info_t::innobase_table_flags()
修改發生位置
./sql/mysqld.cc: //[liuzhuan] 增加一個全局hash存儲算法項
./plugin/daemon_example/daemon_example.cc: //[liuzhuan] 改寫為mysql_pthread(sep-15 second)靜默方式刷盤算法數據
./storage/innobase/handler/ha_innodb.cc: //[liuzhuan] 改寫為向hash存儲算法項,key是table name(排除臨時表),value是算法
./storage/innobase/os/os0file.cc://[liuzhuan] os0file刷盤page位置增加了算法分支,分支的入參是IORequest這個類,算法的判斷依據來自hash內存儲的key
./storage/innobase/include/os0file.h //[liuzhuan] 修改了IORequest這個類,增加了算法判斷的一個表達式,這樣的考慮個人認為是比較妥當的,因為堆棧函數的入參不用去改了
mysql5.6以后內部在alter table上有兩種算法,做如下定義
ALGORITHM=INPLACE
ALGORITHM=COPY
copy table方式
新建跟原表格一致的臨時表,并在該臨時表上執行DDL語句
鎖原表,不允許DML,允許查詢
逐行數據從原表拷貝到臨時表中(這個過程是沒有排序的)
拷貝結束后,原表禁止讀操作,也就是原表此時不提供讀寫服務
進行rename操作,完成DDL過程
inplace方式(fast index creation,僅針對索引的創建跟刪除)
新建frm臨時文件
鎖原表,不允許DML,允許查詢
按照聚集索引的順序,查詢數據,找到需要的索引列數據,排序后插入到新的索引頁中
原表禁止讀操作,也就是原表此時不提供讀寫服務
進行rename操作,替換frm文件,完成DDL過程
這兩種算法的IO行為區別很大,具體在這里不再表述,引用一個博主的文章,對online ddl解釋的非常漂亮了:
SQL語句默認的算法行為
inplace算法
alter table encrypt_test_1 ENCRYPTION='y';
alter table encrypt_test_1 add passtest int(4) default 0, ADD genedetail varchar(50) default '0', encryption='y';
CREATE TABLE `test_5` (
`id` int(11) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL,
`passtest` int(4) DEFAULT '0',
`genedetail` varchar(50) DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ENCRYPTION='n';
CREATE INDEX idd1 ON test_5 (`id`);
ALTER TABLE test_5 ADD INDEX nameid1 (name);
DROP INDEX idd1 ON test_5;
ALTER TABLE test_5 DROP INDEX nameid1;
CREATE FULLTEXT INDEX nameid1 ON test_5(name);
DROP INDEX nameid1 ON test_5;
ALTER TABLE test_5 ADD CONSTRAINT fk_name1 FOREIGN KEY(id) REFERENCES t1(id);
copy算法
CREATE TEMPORARY TABLE aaa as ( select * from encrypt_test_1);
CREATE TABLE aaa as ( select * from encrypt_test_1);
alter table encrypt_test_1 ENCRYPTION='n';
mysql 5.7后版本中的一個bug
CREATE TABLE `test_5` (
`id` int(11) DEFAULT NULL,
`name` varchar(32) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 encryption='y';
然后取消encryption,設置alter table test_5 encryption='n';
最后執行alter table test_5 ENGINE=myisam會出錯,這里在
./storage/myisam/ha_myisam.cc中ha_myisam::create()存在一處bug
2024 if (ha_create_info->encrypt_type.length > 0)
2025│ {
2026│ set_my_errno(HA_WRONG_CREATE_OPTION);
2027│ DBUG_RETURN(HA_WRONG_CREATE_OPTION);
2028│ }
這個條件是不可能失敗的,這樣的結果就是encrypt后的innodb表,轉myisam都會失敗,這在mariadb中是通過table comment解決的,他把這種變革前的語句寫到了comment里,想法也說不上多好
但也算個解決方法吧
他也間接導致sql_table.cc-->mysql_alter_table()函數的copy模式下:
9871行
if (ha_create_table())
goto err_new_table_cleanup; //成立
從而返回 ERROR 1031 (HY000): Table storage engine for '#sql-1ba8_2' doesn't have this option
根據上述兩種算法,在alter table中找到算法發生位置,一共要修改三處
bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name, HA_CREATE_INFO *create_info, ABLE_LIST *table_list, Alter_info *alter_info){
1:
9230行,if (alter_ctx.is_table_renamed()) 他是alter table ... reanme ... 詞法的切入點,這里直接發生調用mysql_rename_table,然后根據執行狀態返回true(失敗)或false(成功)
if (table->s->tmp_table != NO_TMP_TABLE) 判斷是否具備臨時表,table->s->tmp_table有定義好的幾種類型在table.h中定義
引用table.h中定義
enum tmp_table_type
{
NO_TMP_TABLE, NON_TRANSACTIONAL_TMP_TABLE, TRANSACTIONAL_TMP_TABLE, INTERNAL_TMP_TABLE, SYSTEM_TMP_TABLE
};
INTERNAL_TMP_TABLE : 大致如'#sql-5bf6',內部臨時表后是一個動態數,每次mysql重啟,這個動態數都會更新
TRANSACTIONAL_TMP_TABLE : 更多發生在inplace模式,事務性臨時表
這個位置修改alter rename對hash的操作
2:
9733行, switch (inplace_supported) 這里進入inplace模式的處理,這種情況下,if (use_inplace)條件成立
這個位置處理無table io的流程(inplace無io,這里切換hash算法是不能被支持的)
3:
9822行,if (!table->s->tmp_table) 這里進去表拷貝模式
這個位置處理copy io流程下,表的encrypt關鍵字變更
}
總結
以上是生活随笔為你收集整理的mysql有table函数吗_mysql_alter_table函数流程的部分修改和注解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么刷win7系统教程视频 Win7系统
- 下一篇: 联想win10怎么把字体调大 如何在联想