From 1686f5e6f0312b76910afdfe3ab06860f0df8de4 Mon Sep 17 00:00:00 2001 From: wangy102 <31234273+simake2017@users.noreply.github.com> Date: Fri, 18 Jun 2021 15:46:43 +0800 Subject: [PATCH 1/3] Update .gitignore --- .gitignore | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) diff --git a/.gitignore b/.gitignore index d26c37ce2ec..005b29e93fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ + +*.cmake-build-debug/ +*.idea/ + *-t *_test *.Plo @@ -3138,3 +3142,95 @@ storage/perfschema/gen_pfs_lex_token sql/share/bulgarian sql/lex_token.h sql/gen_lex_token +cmake-build-debug/CMakeCache.txt +cmake-build-debug/MySQL.cbp +cmake-build-debug/cmd-line-utils/libedit/makelist +cmake-build-debug/Docs/INFO_SRC +cmake-build-debug/extra/jemalloc/tmp/jemalloc-cfgcmd.txt +cmake-build-debug/extra/jemalloc/tmp/jemalloc-cfgcmd.txt.in +cmake-build-debug/include/my_config.h +cmake-build-debug/include/mysql_version.h +cmake-build-debug/libmysql/libmysql.ver +cmake-build-debug/libmysql/libmysql_exports_file.cc +cmake-build-debug/mysql-test/mtr +cmake-build-debug/mysql-test/mysql-test-run +cmake-build-debug/mysql-test/mysql-test-run.pl +cmake-build-debug/packaging/rpm-docker/my.cnf +cmake-build-debug/packaging/rpm-fedora/my.cnf +cmake-build-debug/packaging/rpm-fedora/my_config.h +cmake-build-debug/packaging/rpm-fedora/mysql-5.6.16-mysql-install.patch +cmake-build-debug/packaging/rpm-fedora/mysql-systemd-start +cmake-build-debug/packaging/rpm-fedora/mysql.conf +cmake-build-debug/packaging/rpm-fedora/mysql_config.sh +cmake-build-debug/packaging/rpm-fedora/mysqld.service +cmake-build-debug/packaging/rpm-oel/filter-provides.sh +cmake-build-debug/packaging/rpm-oel/filter-requires.sh +cmake-build-debug/packaging/rpm-oel/my.cnf +cmake-build-debug/packaging/rpm-oel/my_config.h +cmake-build-debug/packaging/rpm-oel/mysql-5.6.16-mysql-install.patch +cmake-build-debug/packaging/rpm-oel/mysql-systemd-start +cmake-build-debug/packaging/rpm-oel/mysql.conf +cmake-build-debug/packaging/rpm-oel/mysql.init +cmake-build-debug/packaging/rpm-oel/mysql_config.sh +cmake-build-debug/packaging/rpm-oel/mysqld.service +cmake-build-debug/packaging/rpm-sles/filter-provides.sh +cmake-build-debug/packaging/rpm-sles/filter-requires.sh +cmake-build-debug/packaging/rpm-sles/my.cnf +cmake-build-debug/packaging/rpm-sles/my_config.h +cmake-build-debug/packaging/rpm-sles/mysql-systemd-start +cmake-build-debug/packaging/rpm-sles/mysql.conf +cmake-build-debug/packaging/rpm-sles/mysql.init +cmake-build-debug/packaging/rpm-sles/mysqld.service +cmake-build-debug/scripts/make_binary_distribution +cmake-build-debug/scripts/msql2mysql +cmake-build-debug/scripts/mysql_config +cmake-build-debug/scripts/mysql_config.pl +cmake-build-debug/scripts/mysql_convert_table_format +cmake-build-debug/scripts/mysql_find_rows +cmake-build-debug/scripts/mysql_fix_extensions +cmake-build-debug/scripts/mysql_install_db +cmake-build-debug/scripts/mysql_secure_installation +cmake-build-debug/scripts/mysql_setpermission +cmake-build-debug/scripts/mysql_zap +cmake-build-debug/scripts/mysqlaccess +cmake-build-debug/scripts/mysqlaccess.conf +cmake-build-debug/scripts/mysqlbug +cmake-build-debug/scripts/mysqld_multi +cmake-build-debug/scripts/mysqld_safe +cmake-build-debug/scripts/mysqldumpslow +cmake-build-debug/scripts/mysqlhotcopy +cmake-build-debug/sql/sql_builtin.cc +cmake-build-debug/sql-bench/bench-count-distinct +cmake-build-debug/sql-bench/bench-init.pl +cmake-build-debug/sql-bench/compare-results +cmake-build-debug/sql-bench/copy-db +cmake-build-debug/sql-bench/crash-me +cmake-build-debug/sql-bench/example.bat +cmake-build-debug/sql-bench/graph-compare-results +cmake-build-debug/sql-bench/innotest1 +cmake-build-debug/sql-bench/innotest1a +cmake-build-debug/sql-bench/innotest1b +cmake-build-debug/sql-bench/innotest2 +cmake-build-debug/sql-bench/innotest2a +cmake-build-debug/sql-bench/innotest2b +cmake-build-debug/sql-bench/pwd.bat +cmake-build-debug/sql-bench/README +cmake-build-debug/sql-bench/run-all-tests +cmake-build-debug/sql-bench/server-cfg +cmake-build-debug/sql-bench/test-alter-table +cmake-build-debug/sql-bench/test-ATIS +cmake-build-debug/sql-bench/test-big-tables +cmake-build-debug/sql-bench/test-connect +cmake-build-debug/sql-bench/test-create +cmake-build-debug/sql-bench/test-insert +cmake-build-debug/sql-bench/test-select +cmake-build-debug/sql-bench/test-transactions +cmake-build-debug/sql-bench/test-wisconsin +cmake-build-debug/sql-bench/uname.bat +cmake-build-debug/sql/share/dictionary.txt +cmake-build-debug/support-files/binary-configure +cmake-build-debug/support-files/my-default.cnf +cmake-build-debug/support-files/mysql-log-rotate +cmake-build-debug/support-files/mysql.server +cmake-build-debug/support-files/mysqld_multi.server +cmake-build-debug/support-files/plugins.files From 6281affac1e9a6f1e8ec5d44d76f4deed8dc37bc Mon Sep 17 00:00:00 2001 From: wangy102 <31234273+simake2017@users.noreply.github.com> Date: Tue, 22 Jun 2021 14:26:48 +0800 Subject: [PATCH 2/3] =?UTF-8?q?buf=20=E4=B8=8Emem?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extra/innochecksum.cc | 1 + include/my_sys.h | 7 +- mysys/array.c | 8 +- mysys/hash.c | 157 ++++++++++++++++++++++---- mysys/my_thr_init.c | 37 ++++-- mysys/my_winthread.c | 10 +- sql/field.h | 4 +- sql/handler.cc | 8 +- sql/main.cc | 4 + sql/mysqld.cc | 23 +++- sql/sql_base.cc | 18 ++- sql/sql_class.h | 5 +- sql/sql_cmd.h | 6 + sql/sql_lex.h | 24 +++- sql/sql_list.h | 12 +- sql/sql_parse.cc | 21 +++- sql/sql_yacc.yy | 41 ++++++- sql/sys_vars.h | 9 ++ sql/table.h | 19 +++- storage/innobase/buf/buf0buf.cc | 102 +++++++++++++++-- storage/innobase/handler/ha_innodb.cc | 18 ++- storage/innobase/include/buf0buf.h | 6 + storage/innobase/include/buf0buf.ic | 2 +- storage/innobase/include/mem0mem.h | 27 +++++ storage/innobase/include/mem0mem.ic | 10 +- storage/innobase/include/mem0pool.h | 13 +++ storage/innobase/include/ut0byte.ic | 8 +- storage/innobase/include/ut0list.h | 7 ++ storage/innobase/include/ut0lst.h | 11 ++ storage/innobase/include/ut0vec.h | 17 ++- storage/innobase/include/ut0wqueue.h | 9 +- storage/innobase/mem/mem0dbg.cc | 20 +++- storage/innobase/mem/mem0mem.cc | 11 +- storage/innobase/mem/mem0pool.cc | 27 +++++ storage/innobase/os/os0proc.cc | 1 + storage/innobase/srv/srv0srv.cc | 9 +- storage/innobase/srv/srv0start.cc | 7 ++ storage/innobase/ut/ut0mem.cc | 7 ++ strings/ctype-big5.c | 3 + strings/ctype-mb.c | 4 + strings/ctype-utf8.c | 5 +- 41 files changed, 655 insertions(+), 83 deletions(-) diff --git a/extra/innochecksum.cc b/extra/innochecksum.cc index 9c6ca996577..351820b1673 100644 --- a/extra/innochecksum.cc +++ b/extra/innochecksum.cc @@ -103,6 +103,7 @@ get_page_size( flags = mach_read_from_4(buf + FIL_PAGE_DATA + FSP_SPACE_FLAGS); /* srv_page_size is used by InnoDB code as UNIV_PAGE_SIZE */ + //wangyang @@ 这里用于声明 pageSize srv_page_size = *logical_page_size = fsp_flags_get_page_size(flags); /* fsp_flags_get_zip_size() will return zero if not compressed. */ diff --git a/include/my_sys.h b/include/my_sys.h index 24aa4a95ff4..2f739c7ab6a 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -354,9 +354,12 @@ struct st_my_file_info extern struct st_my_file_info *my_file_info; +/** + * wangyang ** st_hash 中使用的动态数组 + */ typedef struct st_dynamic_array { - uchar *buffer; + uchar *buffer; //--> wangyang buffer 字符数组 uint elements,max_element; uint alloc_increment; uint size_of_element; @@ -825,6 +828,8 @@ extern void delete_dynamic(DYNAMIC_ARRAY *array); extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint array_index); extern void freeze_size(DYNAMIC_ARRAY *array); #define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element) +//wangyang *** 这里初始的时候 只是一个 普通的指针,比如 char* 但是会转换为 type 类型,这样宽度就增长了 +//这里只是 获取这个动态数组的 某个位置 #define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) #define push_dynamic(A,B) insert_dynamic((A),(B)) #define reset_dynamic(array) ((array)->elements= 0) diff --git a/mysys/array.c b/mysys/array.c index 0a320085360..f76e84a1cf1 100644 --- a/mysys/array.c +++ b/mysys/array.c @@ -40,6 +40,9 @@ FALSE Ok */ +/** + * wangyang @@ 初始化 动态 数组 + */ my_bool init_dynamic_array2(DYNAMIC_ARRAY *array, uint element_size, void *init_buffer, uint init_alloc, uint alloc_increment) @@ -129,7 +132,7 @@ my_bool insert_dynamic(DYNAMIC_ARRAY *array, const void *element) void *alloc_dynamic(DYNAMIC_ARRAY *array) { - if (array->elements == array->max_element) + if (array->elements == array->max_element) //wangyang 如果 elements已经达到最大数量 那么 需要扩容 { char *new_ptr; if (array->buffer == (uchar *)(array + 1)) @@ -155,6 +158,9 @@ void *alloc_dynamic(DYNAMIC_ARRAY *array) array->buffer= (uchar*) new_ptr; array->max_element+=array->alloc_increment; } + /** + * wangyang 这里就是动态数组中 返回一个 新的元素位置 ,使用 elements + */ return array->buffer+(array->elements++ * array->size_of_element); } diff --git a/mysys/hash.c b/mysys/hash.c index 15a50083798..679956d9d52 100644 --- a/mysys/hash.c +++ b/mysys/hash.c @@ -55,6 +55,10 @@ static my_hash_value_type cset_hash_sort_adapter(const HASH *hash, const uchar *key, size_t length) { + /** + * wangyang ** hash_sort 函数 ,会对 key 值进行 sort 排序 ,这里的排序会在 + * ctype-utf8.c 这种文件里面 跟选定的字符集有关系 + */ ulong nr1=1, nr2=4; hash->charset->coll->hash_sort(hash->charset,(uchar*) key,length,&nr1,&nr2); return (my_hash_value_type)nr1; @@ -107,6 +111,7 @@ _my_hash_init(HASH *hash, uint growth_size, CHARSET_INFO *charset, hash->free=free_element; hash->flags=flags; hash->charset=charset; + //wangyang *** 这里在 进行初始化设置的 时候 如果 hash_function 为NULL ,那么使用 cset_hash_sort_adapter 函数 hash->hash_function= hash_function ? hash_function : cset_hash_sort_adapter; DBUG_RETURN(my_init_dynamic_array_ci(&hash->array, sizeof(HASH_LINK), size, growth_size)); @@ -192,20 +197,45 @@ my_hash_key(const HASH *hash, const uchar *record, size_t *length, my_bool first) { if (hash->get_key) - return (char*) (*hash->get_key)(record,length,first); + return (char*) (*hash->get_key)(record,length,first); //--> 这里会使用 get_key 函数获取相应的key *length=hash->key_length; return (char*) record+hash->key_offset; } /* Calculate pos according to keys */ + /* + * wangyang 这里的 buffmax 就会是 hash结构体的 blength 是2的n次幂 + * 动态hash 生成方式 + * + * 通过 取模的方式 动态生成 hash 值 + */ static uint my_hash_mask(my_hash_value_type hashnr, size_t buffmax, size_t maxlength) { + /** + * wangyang 这里比如 buffmax = 8 max length = 3 那么执行if中语句 + * 如果 buffmax = 9 max length = 3 那么 ,只使用低位 + * + * + * 所以可以看到 动态 hash 每次返回的是不一样的,开始的时候 会尽量在低位,然后逐渐 + * 扩展到 高位 + * + * 一开始的时候 假设 buffmax = 16 maxlength = 0 + * 2、假设 hashnr = 13 & 15 = 13 , 13 > 0,那么 位置么 13 & (16 >> 1) - 1 = 13 & 7 = 7 + * + * 3、假设 hashnr = 13 然后max length = 14 + * 那么 13 & 15 = 13, 13 < 14 ,那么 13 & (16 - 1) = 13 的位置 + * + * + */ if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1)); return (hashnr & ((buffmax >> 1) -1)); } +/* + * wangyang + */ static uint my_hash_rec_mask(const HASH *hash, HASH_LINK *pos, size_t buffmax, size_t maxlength) { @@ -339,6 +369,19 @@ uchar* my_hash_next(const HASH *hash, const uchar *key, size_t length, /* Change link from pos to new_link */ + /** + + 这个函数的目的 是用于 将 HashLink 移动到正确的位置 + + old_link = array + next_link;--> 之前 这个位置的元素 + + 比如一个数组 有10个元素,find 的位置是 8,之前这个位置有一个元素,但是这两个元素 + 不在同一个bucket,因此需要为 将之前这个位置的元素移动到新的位置也就是11(11是新分配的位置) + + 然后 这个元素所在的新桶为 6 ,那么下面这个过程就是从6开始寻找 比如 6的下一个是 4 4的下一个是3 + 3是最后一个 然后赋值 3的 下一个为 11 整个就是这么一个过程 + + */ static void movelink(HASH_LINK *array,uint find,uint next_link,uint newlink) { HASH_LINK *old_link; @@ -383,6 +426,10 @@ static int hashcmp(const HASH *hash, HASH_LINK *pos, const uchar *key, /* Write a hash-key to the hash-index */ + /* + * wangyang *** hash 插入 这里的作用是 往这个 hash 对象中插入一条记录 + * + */ my_bool my_hash_insert(HASH *info, const uchar *record) { int flag; @@ -391,33 +438,84 @@ my_bool my_hash_insert(HASH *info, const uchar *record) uchar *UNINIT_VAR(ptr_to_rec),*UNINIT_VAR(ptr_to_rec2); HASH_LINK *data,*empty,*UNINIT_VAR(gpos),*UNINIT_VAR(gpos2),*pos; - if (HASH_UNIQUE & info->flags) + if (HASH_UNIQUE & info->flags) //wangyang 这里是否是 唯一性 { - uchar *key= (uchar*) my_hash_key(info, record, &idx, 1); + uchar *key= (uchar*) my_hash_key(info, record, &idx, 1); //wangyang * 这里用于生成hahs_key ,可以参考 table_shared if (my_hash_search(info, key, idx)) return(TRUE); /* Duplicate entry */ } flag=0; + /** + * wangyang 这里会对 empty 进行一个 赋值,用于获取数组中一个 空的位置o + * + * empty 这里用于获取一个新的空的位置 这里 empty 地址已经是确定了 + * + * + */ if (!(empty=(HASH_LINK*) alloc_dynamic(&info->array))) return(TRUE); /* No more memory */ - data=dynamic_element(&info->array,0,HASH_LINK*); - halfbuff= info->blength >> 1; - + /* + * wangyang 这里宏定义展开 相当于 array->buffer + array_index + */ + //dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index)) + /** + * wangyang ** 这里的意思是 获取这个 动态数组的 的头位置的指针,也就是array_index为0 + */ + data=dynamic_element(&info->array,0,HASH_LINK*); //wangyang 这里会动态分配一个 element 是 HASH_LINK* 类型的 + halfbuff= info->blength >> 1; //wangyang 是一半的位置 比如 blength 是 8 一半就是4 + + /* + * wangyang ** 主要适用于索引位置,从一半 位置 开始索引 + * 比如blength 是 16 则hashbuff 是 8 + * records 可能是10 + * + * + * idx 用于表示 在数组中的索引位置 + * + * 这里的 first_index 是用 records - 一半 + * + * records 数量 一定是 大于 halfbuff的 因为 是达到blength 的时候 才会放大 一倍 + * + * + * + */ idx=first_index=info->records-halfbuff; + /** + * idx 表示索引位置 + */ if (idx != info->records) /* If some records */ { do { - pos=data+idx; - hash_nr=rec_hashnr(info,pos->data); + pos=data+idx; //wangyang data 是一个指针 + idx + hash_nr=rec_hashnr(info,pos->data); // 用于获取 hash value 值 if (flag == 0) /* First loop; Check if ok */ + /** + * wangyang ** 这里使用了 动态hash 用于生成 动态hash码 + * + * 这几句上下文的 意思是 将会从 records - blength/2 的 pos的位置 进行 重新hash + * + * 如果 下面 重新 hash 之后的结果 不等于 之前的结果 那么 直接 break 就可以了 + * + * 因为上面alloc_dynamic 重新分配了一个元素 ,所以下面的 会使用hash 方法进行重新分配 + * + */ + /** + * + * + * + * + */ if (my_hash_mask(hash_nr, info->blength, info->records) != first_index) break; - if (!(hash_nr & halfbuff)) + /** + * wangyang *** 这里计算得到的 hash 值是 + */ + if (!(hash_nr & halfbuff)) // { /* Key will not move */ - if (!(flag & LOWFIND)) + if (!(flag & LOWFIND)) // 寻找低位的 { if (flag & HIGHFIND) { @@ -449,7 +547,7 @@ my_bool my_hash_insert(HASH *info, const uchar *record) } else { /* key will be moved */ - if (!(flag & HIGHFIND)) + if (!(flag & HIGHFIND)) //--> wangyang *** 这里的意思 是 在高位找到 需要移动的桶了, 然后将 { flag= (flag & LOWFIND) | HIGHFIND; /* key shall be moved to the last (empty) position */ @@ -458,10 +556,10 @@ my_bool my_hash_insert(HASH *info, const uchar *record) } else { - if (!(flag & HIGHUSED)) + if (!(flag & HIGHUSED)) //--> wangyang *** 这里会 进行数据的一个 移动 将 rec2 移动到 gpos2 的位置,然后 empty 的位置就会空出来 { /* Change link of previous hash-key and save */ - gpos2->data=ptr_to_rec2; + gpos2->data=ptr_to_rec2; // wangyang *** 这里 会进行一个移动赋值 gpos2->next=(uint) (pos-data); flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED); } @@ -470,7 +568,7 @@ my_bool my_hash_insert(HASH *info, const uchar *record) } } } - while ((idx=pos->next) != NO_RECORD); + while ((idx=pos->next) != NO_RECORD); // wangyang 这里会 不断的进行遍历,直到 next = no_record if ((flag & (LOWFIND | LOWUSED)) == LOWFIND) { @@ -485,27 +583,48 @@ my_bool my_hash_insert(HASH *info, const uchar *record) } /* Check if we are at the empty position */ + /* + * wangyang 下面是正常流程下 来指定 某个位置 + * + * rec_hashnr 函数用于获取 hash_value + * + * 假定 一开始 不走上面逻辑 ,那么这里获取一个 idx + * + */ + /* + * wangyang 下面计算 idx 是获取到的 bucket 的位置 + */ idx= my_hash_mask(rec_hashnr(info, record), info->blength, info->records + 1); - pos=data+idx; + pos=data+idx; //--> pos 是一个 指针位置 , 这里赋值了 一个地址,所以可以取出对应数据 + /** + * wangyang ** 这里意思是 如果 分配的 位置pos 等于empty 相当于最新的位置 + */ if (pos == empty) { pos->data=(uchar*) record; - pos->next=NO_RECORD; + pos->next=NO_RECORD; //--> 用于声明 next 元素 } else { /* Check if more records in same hash-nr family */ + /** + * 这里会将 pos[0] 的元素 复制到 empty[0] 的位置 这里并不涉及 指针的复制 + * 如果是指针复制 应该是 empty = pos ,所以下面只是一个 元素的复制 + */ empty[0]=pos[0]; + //这里用于获取 pos 位置原先 元素的 bucket + // pos 相同的元素可以认为是 同一个 bucket gpos= data + my_hash_rec_mask(info, pos, info->blength, info->records + 1); - if (pos == gpos) + if (pos == gpos) // 如果在一个 位置 都是同一个bucket 那么 就是 记录 在这个动态数组中的位置 { - pos->data=(uchar*) record; - pos->next=(uint) (empty - data); + pos->data=(uchar*) record; // wangyang 这里存放 当前插入元素 + pos->next=(uint) (empty - data); // 这里是用于 } else { pos->data=(uchar*) record; pos->next=NO_RECORD; + //pos-data 是新元素位置 gpos-data 是 之前 元素的的索引位置 movelink(data,(uint) (pos-data),(uint) (gpos-data),(uint) (empty-data)); } } diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 6d5615035c2..66eb04b0f56 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -113,6 +113,10 @@ void my_thread_global_reinit(void) 1 error (Couldn't create THR_KEY_mysys) */ +/** + * + wangyang 初始化 线程全局 变量 + */ my_bool my_thread_global_init(void) { int pth_ret; @@ -146,21 +150,29 @@ my_bool my_thread_global_init(void) #endif DBUG_ASSERT(! THR_KEY_mysys_initialized); + /** + * wangyang @@@ 这里会 初始化 THR_KEY_mysys(是 通过宏定义定义的变量 ,表示 系统线程 ) + */ if ((pth_ret= pthread_key_create(&THR_KEY_mysys, NULL)) != 0) { fprintf(stderr, "Can't initialize threads: error %d\n", pth_ret); return 1; } - THR_KEY_mysys_initialized= TRUE; + THR_KEY_mysys_initialized= TRUE; //wangyang 这里将 初始化 字段设置为true mysql_mutex_init(key_THR_LOCK_malloc, &THR_LOCK_malloc, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_open, &THR_LOCK_open, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_charset, &THR_LOCK_charset, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_threads, &THR_LOCK_threads, MY_MUTEX_INIT_FAST); - if (my_thread_init()) + if (my_thread_init()) //wangyang 这里进行线程初始化 return 1; + /** + * wangyang ** mysql_mutex_init 会调用 pthread_mutex_init 用于初始化一个结构体 + * + * pthread_cond_init 用于 创建cond 结构体 + */ mysql_mutex_init(key_THR_LOCK_lock, &THR_LOCK_lock, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_THR_LOCK_myisam, &THR_LOCK_myisam, MY_MUTEX_INIT_SLOW); mysql_mutex_init(key_THR_LOCK_myisam_mmap, &THR_LOCK_myisam_mmap, MY_MUTEX_INIT_FAST); @@ -292,8 +304,8 @@ my_bool my_thread_init(void) error= 1; goto end; } - set_mysys_var(tmp); - tmp->pthread_self= pthread_self(); + set_mysys_var(tmp); //wangyang *** 这里用于将初始化的线程设置到 局部变量中 + tmp->pthread_self= pthread_self(); // 线程可以通过调用pthread_self函数获得自身线程标识 返回对象是 pthread_t mysql_mutex_init(key_my_thread_var_mutex, &tmp->mutex, MY_MUTEX_INIT_FAST); mysql_cond_init(key_my_thread_var_suspend, &tmp->suspend, NULL); @@ -301,8 +313,8 @@ my_bool my_thread_init(void) STACK_DIRECTION * (long)my_thread_stack_size; mysql_mutex_lock(&THR_LOCK_threads); - tmp->id= ++thread_id; - ++THR_thread_count; + tmp->id= ++thread_id; //wangyang 线程id 增长 + ++THR_thread_count; //wangyang 线程数量 增长 mysql_mutex_unlock(&THR_LOCK_threads); tmp->init= 1; #ifndef DBUG_OFF @@ -381,13 +393,24 @@ void my_thread_end(void) struct st_my_thread_var *_my_thread_var(void) { - if (THR_KEY_mysys_initialized) + if (THR_KEY_mysys_initialized) //wangyang 如果已经初始化,则从线程局部取出相应的线程局部变量 return my_pthread_getspecific(struct st_my_thread_var*,THR_KEY_mysys); return NULL; } +/** + * wangyang *** + */ int set_mysys_var(struct st_my_thread_var *mysys_var) { + /** + * wangyang *** 用于设置 线程局部变量 这里的作用是将 my_thr_init.c 文件中 my_thread_init 函数中 + * 创建的 st_my_thread_var 变量设置过来 + * + * pthread_getspecific 用于从线程局部变量中 获取相应的 局部变量内容 + * pthread_key_t 表示线程局部变量类型的key + * + */ if (THR_KEY_mysys_initialized) return my_pthread_setspecific_ptr(THR_KEY_mysys, mysys_var); return 0; diff --git a/mysys/my_winthread.c b/mysys/my_winthread.c index fcb6e57ee53..4c995ac673f 100644 --- a/mysys/my_winthread.c +++ b/mysys/my_winthread.c @@ -54,15 +54,18 @@ win_pthread_mutex_trylock(pthread_mutex_t *mutex) static unsigned int __stdcall pthread_start(void *p) { - struct thread_start_parameter *par= (struct thread_start_parameter *)p; + struct thread_start_parameter *par= (struct thread_start_parameter *)p; //转为 thread_start_parameter pthread_handler func= par->func; void *arg= par->arg; free(p); - (*func)(arg); + (*func)(arg); //wangyang 调用传入进来的相应的函数 return 0; } +/** + * wangyang 这里是 mysql 用于创建 pthread_create + */ int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr, pthread_handler func, void *param) { @@ -80,6 +83,9 @@ int pthread_create(pthread_t *thread_id, const pthread_attr_t *attr, par->arg= param; stack_size= attr?attr->dwStackSize:0; + /** + * wangyang 调用系统调用 + */ handle= _beginthreadex(NULL, stack_size , pthread_start, par, 0, thread_id); if (!handle) goto error_return; diff --git a/sql/field.h b/sql/field.h index 12e6c0eedae..15dde2cffb9 100644 --- a/sql/field.h +++ b/sql/field.h @@ -449,7 +449,9 @@ void copy_integer(uchar *to, int to_length, } } - +/** + * wangyang ** Field 表示字段类,用 Item 进行初始化 + */ class Field { Field(const Item &); /* Prevent use of these */ diff --git a/sql/handler.cc b/sql/handler.cc index 405963acfe0..2c90b6791b5 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -7611,10 +7611,14 @@ int handler::ha_reset() DBUG_RETURN(retval); } - +/** + * + wangyang ** handler是存储引擎的基类 + */ int handler::ha_write_row(uchar *buf) { int error; + //wangyang ** 指定 log event 类型 Log_func *log_func= Write_rows_log_event::binlog_row_logging_function; DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE || m_lock_type == F_WRLCK); @@ -7627,7 +7631,7 @@ int handler::ha_write_row(uchar *buf) mark_trx_read_write(); MYSQL_TABLE_IO_WAIT(m_psi, PSI_TABLE_WRITE_ROW, MAX_KEY, 0, - { error= write_row(buf); limit_io(ha_thd()); }) + { error= write_row(buf); limit_io(ha_thd()); }) //wangyang ** 具体写入 MYSQL_INSERT_ROW_DONE(error); if (unlikely(error)) diff --git a/sql/main.cc b/sql/main.cc index 4da4d6c2775..a1417bf3555 100644 --- a/sql/main.cc +++ b/sql/main.cc @@ -20,6 +20,10 @@ */ extern int mysqld_main(int argc, char **argv); +/** + * + wangyang *** mysql启动入口函数 + */ int main(int argc, char **argv) { return mysqld_main(argc, argv); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 5f1ffd2c247..f6d17061976 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -4765,6 +4765,9 @@ initialize_storage_engine(char *se_name, const char *se_kind, } +/* + * 在 mysql + */ static int init_server_components() { DBUG_ENTER("init_server_components"); @@ -4773,6 +4776,9 @@ static int init_server_components() all things are initialized so that unireg_abort() doesn't fail */ mdl_init(); + /** + * wangyang ** 这里初始化 table_def_cache + */ if (table_def_init() | hostname_cache_init(host_cache_size)) unireg_abort(1); @@ -5364,6 +5370,10 @@ static void hash_item_free_entry(ic_hash_item_t *record) #ifdef __WIN__ int win_main(int argc, char **argv) #else +/** + * + wangyang @@ 启动入口 main 函数 这里 初始化 调用mysqld_main + */ int mysqld_main(int argc, char **argv) #endif { @@ -5377,7 +5387,10 @@ int mysqld_main(int argc, char **argv) #ifndef _WIN32 // For windows, my_init() is called from the win specific mysqld_main - if (my_init()) // init my_sys library & pthreads + /** + * wangyang ** 用于进行初始化 + */ + if (my_init()) // 注释说的很清楚 ,用于初始化 系统变量 和 pthread // init my_sys library & pthreads { fprintf(stderr, "my_init() failed."); return 1; @@ -5387,6 +5400,9 @@ int mysqld_main(int argc, char **argv) orig_argc= argc; orig_argv= argv; my_getopt_use_args_separator= TRUE; + /** + * wangyang @@ 这里会加载 配置文件 ,初始化 配置文件 my.cnf + */ if (load_defaults(MYSQL_CONFIG_NAME, load_default_groups, &argc, &argv)) return 1; my_getopt_use_args_separator= FALSE; @@ -5399,7 +5415,7 @@ int mysqld_main(int argc, char **argv) system_charset_info= &my_charset_utf8_general_ci; init_sql_statement_names(); - sys_var_init(); + sys_var_init(); //wangyang 初始化系统变量 跟上面的 load_default有先后顺序,先使用上面 进行 load_defaults int ho_error; @@ -5626,6 +5642,9 @@ int mysqld_main(int argc, char **argv) Service.SetSlowStarting(slow_start_timeout); #endif + /** + * 在mysqld.cc 的 init 函数中调用该方法,用于初始化 服务组件 + */ if (init_server_components()) unireg_abort(1); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 97f7cb67ae6..353299b08dd 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -329,10 +329,13 @@ uint get_table_def_key(const TABLE_LIST *table_list, const char **key) Functions to handle table definition cach (TABLE_SHARE) *****************************************************************************/ +/** + * wangyang ** table_def key对象 + */ extern "C" uchar *table_def_key(const uchar *record, size_t *length, my_bool not_used MY_ATTRIBUTE((unused))) { - TABLE_SHARE *entry=(TABLE_SHARE*) record; + TABLE_SHARE *entry=(TABLE_SHARE*) record; //wangyang * 直接将数据进行类型转换 *length= entry->table_cache_key.length; return (uchar*) entry->table_cache_key.str; } @@ -355,7 +358,10 @@ static void table_def_free_entry(TABLE_SHARE *share) DBUG_VOID_RETURN; } - +/** + * wangyang 用于初始化 表对象 + * @return + */ bool table_def_init(void) { #ifdef HAVE_PSI_INTERFACE @@ -377,6 +383,9 @@ bool table_def_init(void) */ table_def_inited= true; + /** + * wangyang **** 这里是 会初始化相应的 table_def_cache 这个数据结构 + */ return my_hash_init(&table_def_cache, &my_charset_bin, table_def_size, 0, 0, table_def_key, (my_hash_free_key) table_def_free_entry, 0) != 0; @@ -454,6 +463,11 @@ uint cached_table_definitions(void) # Share for table */ +/* + * wangyang ** 这里用于从 table_def_cache 中获取 共享表数据 + * + * key 是 表名称的意思 + */ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, const char *key, uint key_length, uint db_flags, int *error, diff --git a/sql/sql_class.h b/sql/sql_class.h index 31b2abbbfa6..9abfebbaa67 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -5597,7 +5597,10 @@ void add_diff_to_status(STATUS_VAR *to_var, STATUS_VAR *from_var, STATUS_VAR *dec_var); /* Inline functions */ - +/** + * + wangyang ** 这里会将 item 加入到thd里面 + */ inline bool add_item_to_list(THD *thd, Item *item) { return thd->lex->current_select->add_item_to_list(thd, item); diff --git a/sql/sql_cmd.h b/sql/sql_cmd.h index c30931af291..561a1476c99 100644 --- a/sql/sql_cmd.h +++ b/sql/sql_cmd.h @@ -30,6 +30,12 @@ added SQLCOM_. */ +/* + * + * wangyang ** 相关的sql 命令 + * + * + */ enum enum_sql_command { SQLCOM_SELECT, SQLCOM_CREATE_TABLE, SQLCOM_CREATE_INDEX, SQLCOM_ALTER_TABLE, SQLCOM_UPDATE, SQLCOM_INSERT, SQLCOM_INSERT_SELECT, diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9b9c443d6e2..7bbb76e424f 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -694,6 +694,9 @@ class st_select_lex: public st_select_lex_node LEX *parent_lex; enum olap_type olap; /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */ + /** + * + */ SQL_I_List table_list; /* @@ -711,6 +714,9 @@ class st_select_lex: public st_select_lex_node SELECT: Fields and expressions in the SELECT list. UPDATE: Fields in the SET clause. */ + /* + * wangyang 用于表示 存储过程中的 各种 field + */ List item_list; List interval_list; bool is_item_list_lookup; @@ -732,6 +738,11 @@ class st_select_lex: public st_select_lex_node inlcude all base tables including view tables. The tables are connected by TABLE_LIST::next_leaf, so leaf_tables points to the left-most leaf. */ + + /** + * wangyang ** 用于表示 相应的叶子节点 + * + */ TABLE_LIST *leaf_tables; /** SELECT_LEX type enum @@ -1135,6 +1146,9 @@ class Query_tables_list */ enum_sql_command sql_command; /* Global list of all tables used by this statement */ + /** + * wangyang ** statement 对应的 table list (statement 对应一条sql) + */ TABLE_LIST *query_tables; /* Pointer to next_global member of last element in the previous list. */ TABLE_LIST **query_tables_last; @@ -2253,12 +2267,20 @@ struct Proc_analyse_params: public Sql_alloc /* The state of the lex parsing. This is saved in the THD struct */ - +/* + * wangyang ** 语法 解析对象 + */ struct LEX: public Query_tables_list { SELECT_LEX_UNIT unit; /* most upper unit */ + /** + * wangyang ** select_lex 里面 用于存储 相应的 解析出的 sql 语法语句 + */ SELECT_LEX select_lex; /* first SELECT_LEX */ /* current SELECT_LEX in parsing */ + /* + * 用于解析 过程中的 current select 语句 + */ SELECT_LEX *current_select; /* list of all SELECT_LEX */ SELECT_LEX *all_selects_list; diff --git a/sql/sql_list.h b/sql/sql_list.h index b73cc313bd5..4d0da56c11b 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -109,6 +109,9 @@ class SQL_I_List :public Sql_alloc @note We never call a destructor for instances of this class. */ +/* + * wangyang list_node 代表一个 node , info 表示 当前指向的节点 + */ struct list_node :public Sql_alloc { list_node *next; @@ -398,8 +401,8 @@ class base_list_iterator inline void init(base_list &list_par) { - list= &list_par; - el= &list_par.first; + list= &list_par; //wangyang 表示整个list + el= &list_par.first; //wangyang el用于记录 第一个 prev= 0; current= 0; } @@ -411,6 +414,9 @@ class base_list_iterator el= ¤t->next; return current->info; } + /* + * wangyang el 代表当前项 + */ inline void *next_fast(void) { list_node *tmp; @@ -532,7 +538,7 @@ template class List_iterator_fast :public base_list_iterator inline List_iterator_fast(List &a) : base_list_iterator(a) {} inline List_iterator_fast() : base_list_iterator() {} inline void init(List &a) { base_list_iterator::init(a); } - inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } + inline T* operator++(int) { return (T*) base_list_iterator::next_fast(); } //wangyang ** 重写了 ++ 运算符 inline void rewind(void) { base_list_iterator::rewind(); } void sublist(List &list_arg, uint el_arg) { diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d2221cea9b0..3718e9f59b0 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -2488,7 +2488,7 @@ mysql_execute_command(THD *thd) */ lex->first_lists_tables_same(); /* should be assigned after making first tables same */ - all_tables= lex->query_tables; + all_tables= lex->query_tables; //wangyang 列举所有的 tables /* set context for commands which do not use setup_tables */ select_lex-> context.resolve_in_table_list_only(select_lex-> @@ -2521,7 +2521,7 @@ mysql_execute_command(THD *thd) !rpl_filter->db_ok(thd->db)) DBUG_RETURN(0); - if (lex->sql_command == SQLCOM_DROP_TRIGGER) + if (lex->sql_command == SQLCOM_DROP_TRIGGER) // wangyang 删除触发器 { /* When dropping a trigger, we need to load its table name @@ -3608,7 +3608,7 @@ case SQLCOM_PREPARE: DBUG_PRINT("debug", ("Just after generate_incident()")); } #endif - case SQLCOM_INSERT: + case SQLCOM_INSERT: //wangyang ** 这里执行 插入语句 { DBUG_ASSERT(first_table == all_tables && first_table != 0); @@ -3628,6 +3628,13 @@ case SQLCOM_PREPARE: MYSQL_INSERT_START(thd->query()); check_queue_on_pk(thd, all_tables, lex); + /** + * wangyang ** 这里用于 执行 sql 插入 + * + * field_list 表示 字段 + * all_tables 表示 所有的表 + * + */ res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values, lex->update_list, lex->value_list, lex->duplicates, lex->ignore); @@ -6487,6 +6494,9 @@ void mysql_init_multi_delete(LEX *lex) the next query in the query text. */ +/* + * wangyang *** sql查询解析 + */ void mysql_parse(THD *thd, char *rawbuf, uint length, Parser_state *parser_state) { @@ -6518,6 +6528,9 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, { LEX *lex= thd->lex; + /** + * wangyang ** 这里将sql 进行词法转换分析 + */ bool err= parse_sql(thd, parser_state, NULL); const char *found_semicolon= parser_state->m_lip.found_semicolon; @@ -6613,7 +6626,7 @@ void mysql_parse(THD *thd, char *rawbuf, uint length, } else { - error= mysql_execute_command(thd); + error= mysql_execute_command(thd); //wangyang ** 这里执行 command if (!thd->trx_end_by_hint) { if (!error && lex->ci_on_success) diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c29c79aed9e..b6996c64f64 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -8807,6 +8807,16 @@ opt_ignore_leaves: Select : retrieve data from table */ +/* + + 杩欓噷浣跨敤 bison bison涓娇鐢ㄤ簡澶ч噺 c++浠g爜锛屽皢瑙f瀽缁撴灉 宓屽叆鍒 瀵瑰簲鐨刢++瀵硅薄涓 + 姣斿LEX + +绗竴姝 1銆 wangyang *** select璇彞鍏ュ彛 + +杩欓噷鏄 鍏ュ彛閮ㄥ垎 select 璧峰璇彞 锛宻elect_init 涔熸槸涓涓〃杈惧紡 浼氱户缁鎵 + +*/ select: select_init @@ -8819,13 +8829,17 @@ select: /* SELECT...UPDATE is regarded as a DML.*/ if (lex->sql_command != SQLCOM_UPDATE) - lex->sql_command= SQLCOM_SELECT; + lex->sql_command= SQLCOM_SELECT; //wangyang 杩欓噷鐢ㄤ簬鍒濆鍖 鍛戒护 } ; /* Need select_init2 for subselects. */ +/* +绗簩姝 2銆 SELECT_SYM 涓簊elect 鍏抽敭瀛 +wangyang 杩欓噷鐨勭洰鐨勬槸宓屽瀛愬惊鐜 +*/ select_init: - SELECT_SYM select_init2 + SELECT_SYM select_init2 /* wangyang 杩欓噷浼 鍒濆鍖栧煄 缁堢粨绗 select select_init2 select_init2缁х画瀵绘壘 */ | '(' select_paren ')' union_opt ; @@ -8848,8 +8862,11 @@ select_paren_derived: | '(' select_paren_derived ')' ; +/* +绗笁姝 3 wangyang +*/ select_init2: - select_part2 + select_part2 /* wangyang 鐢ㄤ簬璁剧疆 */ { LEX *lex= Lex; SELECT_LEX * sel= lex->current_select; @@ -8868,6 +8885,10 @@ select_init2: union_clause ; +/* +绗洓姝 wangyang ** +杩欓噷瑙f瀽涓 select_part2 +*/ select_part2: { LEX *lex= Lex; @@ -8883,7 +8904,7 @@ select_part2: MYSQL_YYABORT; } } - select_options select_item_list + select_options select_item_list /*wangyang ** 杩欓噷鐨勭洰鐨勬槸 鐢ㄦ潵瑙f瀽鍒楀悕 , 杩欓噷浼氬睍寮 select_item_list瀛愬彞 */ { Select->parsing_place= NO_MATTER; } @@ -9080,6 +9101,10 @@ select_lock_type: } ; +/* + 杩欓噷浼氱户缁睍寮 杩欓噷鍒涘缓涓涓 item_field 骞朵笖璋冪敤add_item_to_list + 浼氭爣璁 current_select 褰撳墠瀛愬彞锛屽洜涓 鏈夊彲鑳藉瓨鍦ㄥ祵濂楋紝鎵浠 闇瑕佷娇鐢 current_select 杩涜鏍囪 +*/ select_item_list: select_item_list ',' select_item | select_item @@ -9097,6 +9122,9 @@ select_item_list: } ; +/** +wangyang 杩欓噷灏嗘瘡涓 瀛楁瑙f瀽鎴恑tem +*/ select_item: remember_name table_wild remember_end { @@ -9155,6 +9183,9 @@ optional_braces: ; /* all possible expressions */ +/* +wangyang 杩欓噷鐢ㄤ簬瑙i噴琛ㄨ揪寮 +*/ expr: expr or expr %prec OR_SYM { @@ -11536,7 +11567,7 @@ where_clause: { Select->parsing_place= IN_WHERE; } - expr + expr /*wangyang 琛ㄨ揪寮*/ { SELECT_LEX *select= Select; select->where= $3; diff --git a/sql/sys_vars.h b/sql/sys_vars.h index 2ed5ab61836..a4eba799a8a 100644 --- a/sql/sys_vars.h +++ b/sql/sys_vars.h @@ -102,6 +102,15 @@ struct CMD_LINE Backing store: uint, ulong, ha_rows, ulonglong, long, depending on the Sys_var_* */ + +/** + * + wangyang 这里使用了 模板模式 并且继承了 sys_var 对象 + + 只要 创建相应的对象就会使用 all_sys_vars 将变量注册到全局变量中 + + + */ template class Sys_var_integer: public sys_var diff --git a/sql/table.h b/sql/table.h index a2f33b4168c..11d3d214d9f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -578,8 +578,11 @@ typedef I_P_List frame = frame; + block->frame = frame; // 这里是指向 相应的 Page内存的地址 - block->page.buf_pool_index = buf_pool_index(buf_pool); + block->page.buf_pool_index = buf_pool_index(buf_pool); // 设置所属的 buf pool block->page.state = BUF_BLOCK_NOT_USED; block->page.buf_fix_count = 0; block->page.io_fix = BUF_IO_NONE; @@ -1089,6 +1092,9 @@ buf_block_init( /********************************************************************//** Allocates a chunk of buffer frames. @return chunk, or NULL on failure */ +/** + * wangyang @@@ 这里是初始化 buf chunk + */ static buf_chunk_t* buf_chunk_init( @@ -1096,6 +1102,7 @@ buf_chunk_init( buf_pool_t* buf_pool, /*!< in: buffer pool instance */ buf_chunk_t* chunk, /*!< out: chunk of buffers */ ulint mem_size) /*!< in: requested size in bytes */ + //wangyang @@ 这里的mem_size 就是 每个 buf instance 的大小 { buf_block_t* block; byte* frame; @@ -1103,13 +1110,18 @@ buf_chunk_init( /* Round down to a multiple of page size, although it already should be. */ + //((n) & ~((m) - 1)) + //wangyang @@ 这会通过位运算 获取相应的 对数位, 这里的目的是将 mem_size 对齐到 Page(16k) 的2次幂 也就是16k的倍数 + // 比如这里 申请的 mem_size 大小是 16k + 3 那么对齐之后,就是16k mem_size = ut_2pow_round(mem_size, UNIV_PAGE_SIZE); /* Reserve space for the block descriptors. */ + //wangyang @@ 这里的目的是 需要在添加相应的 block空间 , 比如 申请空间大小是 16k * 10 ,那么就是 10 * 4 这样, + // 这里是 sizeof (*block) block是一个指针,所以实际申请的是 整个 buf_block_t 的数据块的大小 mem_size += ut_2pow_round((mem_size / UNIV_PAGE_SIZE) * (sizeof *block) + (UNIV_PAGE_SIZE - 1), UNIV_PAGE_SIZE); chunk->mem_size = mem_size; - chunk->mem = os_mem_alloc_large(&chunk->mem_size); + chunk->mem = os_mem_alloc_large(&chunk->mem_size); //wangyang 这里是分配具体的内存 if (UNIV_UNLIKELY(chunk->mem == NULL)) { @@ -1132,16 +1144,40 @@ buf_chunk_init( } #endif // HAVE_LIBNUMA + /* + + struct buf_chunk_t{ + ulint mem_size; !< allocated size of the chunk + ulint size; !< size of frames[] and blocks[] + void* mem; !< pointer to the memory area which + was allocated for the frames + buf_block_t* blocks; !< array of buffer control blocks wangyang @@ 这里就是提到的 chunk 块 ,每个chunk块包含多个block对象 +}; + */ + /* Allocate the block descriptors from the start of the memory block. */ - chunk->blocks = (buf_block_t*) chunk->mem; + /** + * wangyang @@ 这里将 mem 分配成为 buf_block_t * 指针 + */ + chunk->blocks = (buf_block_t*) chunk->mem; //wangyang mem 对应着分配的内存 /* Align a pointer to the first frame. Note that when os_large_page_size is smaller than UNIV_PAGE_SIZE, we may allocate one fewer block than requested. When it is bigger, we may allocate more blocks than requested. */ + /** + * wangyang @@@ 这里会 将 mem 按照8k 进行对齐, 主要是将首地址 按照固定格式对齐 + */ frame = (byte*) ut_align(chunk->mem, UNIV_PAGE_SIZE); + //wangyang 这里用于 获取 Page 的数量 + /** + * wangyang @@@ 这里的mem_size 是 合并 初始的 size 以及后面 添加的 *block_t 的混合 + * + * + * + */ chunk->size = chunk->mem_size / UNIV_PAGE_SIZE - (frame != chunk->mem); @@ -1149,23 +1185,41 @@ buf_chunk_init( { ulint size = chunk->size; + /** + * wangyang @@@ 这里很精妙,主要的作用是将整个mem内存分成 + * 2部分,一部分是头,一部分是 每个Page,相当于每个Page + * 会有一个对应的指针 + * + * 这里的目的是找到 block_t 与frame 的分界点,frame 按照 Page 前进, + * + * + */ while (frame < (byte*) (chunk->blocks + size)) { - frame += UNIV_PAGE_SIZE; - size--; + frame += UNIV_PAGE_SIZE; // wangyang @@ 这里会让 frame 按照Page 进行前进 + size--; //wangyang @@ 因为上面 前进了Page , 所以这里 需要减掉,否则 会超出相应的 内存使用界限 } - chunk->size = size; + chunk->size = size; // wangyang @@@ 这里会修改 真正 的size 数量 } /* Init block structs and assign frames for them. Then we assign the frames to the first blocks (we already mapped the memory above). */ + /** + * wangyang @@@ 所以可以看到 具体的 block 块的指针在 chunk 结构体中 blocks 字段 + */ block = chunk->blocks; + /** + * wangyang @@ 这里会对 block 进行 初始化 + */ for (i = chunk->size; i--; ) { - buf_block_init(buf_pool, block, frame); + /** + * wangyang @@@ 这里会初始化 + */ + buf_block_init(buf_pool, block, frame); //wangyang 这里初始化每个Page UNIV_MEM_INVALID(block->frame, UNIV_PAGE_SIZE); /* Add the block to the free list */ @@ -1175,7 +1229,7 @@ buf_chunk_init( ut_ad(buf_pool_from_block(block) == buf_pool); block++; - frame += UNIV_PAGE_SIZE; + frame += UNIV_PAGE_SIZE; //wangyang 这里不断遍历每个Page } #ifdef PFS_GROUP_BUFFER_SYNC @@ -1317,6 +1371,10 @@ buf_pool_set_sizes(void) /********************************************************************//** Initialize a buffer pool instance. @return DB_SUCCESS if all goes well. */ +/* + * wangyang @@@ 这里 buf pool instance 实例初始化 + * 使用的时候 会分配相应的chunk 进行初始化 + */ UNIV_INTERN ulint buf_pool_init_instance( @@ -1338,13 +1396,26 @@ buf_pool_init_instance( buf_pool_mutex_enter(buf_pool); if (buf_pool_size > 0) { + + /** + * + */ buf_pool->n_chunks = 1; + /** + * wangyang @@ 初始的时候 只有一个 chunk + */ buf_pool->chunks = chunk = (buf_chunk_t*) mem_zalloc(sizeof *chunk); UT_LIST_INIT(buf_pool->free); + /** + * wangyang @@ 这里会初始化 chunk ,这里的初始化 会将所有的内存都初始化为 chunk (一次性初始化) + * + * 并没有 进行 分隔 + * + */ if (!buf_chunk_init(buf_pool, chunk, buf_pool_size)) { mem_free(chunk); mem_free(buf_pool); @@ -1469,7 +1540,7 @@ buf_pool_init( ulint n_instances) /*!< in: number of instances */ { ulint i; - const ulint size = total_size / n_instances; + const ulint size = total_size / n_instances; //wangyang @@ 这里会使用 total size / count 获取相应实例数量 ut_ad(n_instances > 0); ut_ad(n_instances <= MAX_BUFFER_POOLS); @@ -1490,12 +1561,21 @@ buf_pool_init( } #endif // HAVE_LIBNUMA +/** + * wangyang @@ 这里进行计算, + */ + /** + * wangyang @@@ 这里分配的是 当前这个 pool 数组的大小 + */ buf_pool_ptr = (buf_pool_t*) mem_zalloc( n_instances * sizeof *buf_pool_ptr); for (i = 0; i < n_instances; i++) { buf_pool_t* ptr = &buf_pool_ptr[i]; + /** + * wangyang @@ 这里会 一个一个的 初始化 每个 instance + */ if (buf_pool_init_instance(ptr, size, i) != DB_SUCCESS) { /* Free all the instances created so far. */ diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 6ce4da48bfe..88b73ae880a 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -2978,6 +2978,9 @@ ha_innobase::init_table_handle_for_HANDLER(void) /*********************************************************************//** Opens an InnoDB database. @return 0 on success, error code on failure */ +/** + * wangyang @@ 这里初始化 innobase + */ static int innobase_init( @@ -3484,6 +3487,9 @@ innobase_init( modules, we check at run time that the size is the same in these compilation modules. */ + /** + * wangyang @@@ 这里初始化 启动 innobase + */ err = innobase_start_or_create_for_mysql(); if (err != DB_SUCCESS) { @@ -6710,6 +6716,10 @@ ha_innobase::innobase_set_max_autoinc( Stores a row in an InnoDB database, to the table specified in this handle. @return error code */ + +/** + * wangyang *** 这里用于 写入行信息 + */ UNIV_INTERN int ha_innobase::write_row( @@ -6859,6 +6869,9 @@ ha_innobase::write_row( innobase_srv_conc_enter_innodb(prebuilt->trx); + /** + * wangyang ** 具体的 行信息插入 + */ error = row_insert_for_mysql((byte*) record, prebuilt); DEBUG_SYNC(user_thd, "ib_after_row_insert"); @@ -17237,6 +17250,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { NULL }; +/** + * wangyang @@ 这里会声明 mysql 的初始插件 + */ mysql_declare_plugin(innobase) { MYSQL_STORAGE_ENGINE_PLUGIN, @@ -17245,7 +17261,7 @@ mysql_declare_plugin(innobase) plugin_author, "Supports transactions, row-level locking, and foreign keys", PLUGIN_LICENSE_GPL, - innobase_init, /* Plugin Init */ + innobase_init, /* Plugin Init */ //wangyang innobase 初始化 插件 NULL, /* Plugin Deinit */ INNODB_VERSION_SHORT, innodb_status_variables_export,/* status variables */ diff --git a/storage/innobase/include/buf0buf.h b/storage/innobase/include/buf0buf.h index 9d3521a0f06..b5e52c7d3e7 100644 --- a/storage/innobase/include/buf0buf.h +++ b/storage/innobase/include/buf0buf.h @@ -1620,6 +1620,12 @@ struct buf_page_t{ /** The buffer control block structure */ +/* + * wangyang @@@ 这里的使用在 buf chunk 当中 buf0buf.ic 里面 + * 也就是我们之前 看到的 buf pool 里面会分成很多 的 block + * 然后 每个 block 又会进行划分 + * + */ struct buf_block_t{ /** @name General fields */ diff --git a/storage/innobase/include/buf0buf.ic b/storage/innobase/include/buf0buf.ic index 56616c6deeb..dcba678707a 100644 --- a/storage/innobase/include/buf0buf.ic +++ b/storage/innobase/include/buf0buf.ic @@ -42,7 +42,7 @@ struct buf_chunk_t{ ulint size; /*!< size of frames[] and blocks[] */ void* mem; /*!< pointer to the memory area which was allocated for the frames */ - buf_block_t* blocks; /*!< array of buffer control blocks */ + buf_block_t* blocks; /*!< array of buffer control blocks */ /* wangyang @@ 这里就是提到的 chunk 块 ,每个chunk块包含多个block对象 */ }; /*********************************************************************//** diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index de9b8b29fd9..8a74392b618 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -133,6 +133,9 @@ memory heap. For debugging purposes, takes also the file name and line as arguments. @return own: memory heap, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps) */ +/* + * wangyang @@ mem_heap_create 函数 , 用于创建相应的 mem_heap 具体在 mem0mem.ic当中 + */ UNIV_INLINE mem_heap_t* mem_heap_create_func( @@ -172,6 +175,10 @@ mem_heap_zalloc( Allocates n bytes of memory from a memory heap. @return allocated storage, NULL if did not succeed (only possible for MEM_HEAP_BTR_SEARCH type heaps) */ +/** + wangyang @@ 这里是从 heap 中分配 相应的内存大小 + 参数包括 一个 mem_heap_t 以及一个 请求大小数量 + */ UNIV_INLINE void* mem_heap_alloc( @@ -237,6 +244,10 @@ Macro for memory buffer allocation */ #define mem_zalloc(N) memset(mem_alloc(N), 0, (N)) +/* + __LINE__:在源代码中插入当前源代码行号; + __FILE__:在源文件中插入当前源文件名; + */ #ifdef UNIV_DEBUG #define mem_alloc(N) mem_alloc_func((N), __FILE__, __LINE__, NULL) #define mem_alloc2(N,S) mem_alloc_func((N), __FILE__, __LINE__, (S)) @@ -251,6 +262,9 @@ Allocates a single buffer of memory from the dynamic memory of the C compiler. Is like malloc of C. The buffer must be freed with mem_free. @return own: free storage */ +/* + * wangyang 从动态内存中分配内存 + */ UNIV_INLINE void* mem_alloc_func( @@ -368,6 +382,16 @@ mem_validate_all_blocks(void); /*#######################################################################*/ /** The info structure stored at the beginning of a heap block */ +/** + * wangyang @@ 下面的 mem_block_info_t 就是 mem_heap_t结构体 + * 里面会有 mem_block_t 形成链表 , mem_block_t 就是 mem_block_info_t + * block 的内存 来源于 mem_pool (mem_pool 形成类似 buddy的分配方式) + * + * 1、 + * + * + * + */ struct mem_block_info_t { ulint magic_n;/* magic number for debugging */ #ifdef UNIV_DEBUG @@ -387,6 +411,9 @@ struct mem_block_info_t { node and is set to ULINT_UNDEFINED in others. */ ulint type; /*!< type of heap: MEM_HEAP_DYNAMIC, or MEM_HEAP_BUF possibly ORed to MEM_HEAP_BTR_SEARCH */ + /** + * wangyang @@ 这里是 空闲内存的地址 + */ ulint free; /*!< offset in bytes of the first free position for user data in the block */ ulint start; /*!< the value of the struct field 'free' at the diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index 63e68150b61..db845cb8adc 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -186,7 +186,7 @@ mem_heap_alloc( ut_ad(mem_heap_check(heap)); - block = UT_LIST_GET_LAST(heap->base); + block = UT_LIST_GET_LAST(heap->base); //wangyang @@ 这里用于获取 相应的 heap的 base 地址 ut_ad(!(block->type & MEM_HEAP_BUFFER) || (n <= MEM_MAX_ALLOC_IN_BUF)); @@ -204,6 +204,10 @@ mem_heap_alloc( } } + /* + wangyang @@从 heap 中寻找出 符合条件的内存块 + 这里从 当前 heap 寻找符合条件内存 然后添加 block 首地址 + */ free = mem_block_get_free(block); buf = (byte*) block + free; @@ -446,6 +450,7 @@ mem_heap_create_func( n = MEM_BLOCK_START_SIZE; } + // wangyang mem_heap_t 同时也是 mem_block_t 是同一个对象,内存数据来源于 mem_pool block = mem_heap_create_block(NULL, n, type, file_name, line); if (block == NULL) { @@ -460,6 +465,9 @@ mem_heap_create_func( #ifdef UNIV_MEM_DEBUG + /* + wangyang 这里是插入到相应的hash 当中,会按照文件名称 以及 line 进行hash + */ mem_hash_insert(block, file_name, line); #endif diff --git a/storage/innobase/include/mem0pool.h b/storage/innobase/include/mem0pool.h index a65ba50fdf9..1d0d0672304 100644 --- a/storage/innobase/include/mem0pool.h +++ b/storage/innobase/include/mem0pool.h @@ -37,11 +37,24 @@ struct mem_pool_t; extern mem_pool_t* mem_comm_pool; /** Memory area header */ +/** + * wangyang @@ 声明内存头 + */ struct mem_area_t{ ulint size_and_free; /*!< memory area size is obtained by anding with ~MEM_AREA_FREE; area in a free list if ANDing with MEM_AREA_FREE results in nonzero */ + /** + * wangyang 这里会以 mem_area_t 作为一个 节点 + */ + /* + 每个 free_list 类似于 一个 Node节点,有 前驱和后继 prev 和 next + struct ut_list_node { + TYPE* prev; + TYPE* next; + }; + */ UT_LIST_NODE_T(mem_area_t) free_list; /*!< free list node */ }; diff --git a/storage/innobase/include/ut0byte.ic b/storage/innobase/include/ut0byte.ic index 873d98c727e..642b1c8b967 100644 --- a/storage/innobase/include/ut0byte.ic +++ b/storage/innobase/include/ut0byte.ic @@ -84,12 +84,18 @@ ut_align( const void* ptr, /*!< in: pointer */ ulint align_no) /*!< in: align by this number */ { - ut_ad(align_no > 0); + ut_ad(align_no > 0); //wangyang @@ 这里的 ut_ad 是 assert 是断言 进行判断是否 ut_ad(((align_no - 1) & align_no) == 0); ut_ad(ptr); ut_ad(sizeof(void*) == sizeof(ulint)); + /** + wangyang @@@ 这里会通过对齐的方式 获取 相应的对齐地址 + 比如这里 会进行一个对齐,比如pageNo = 16 ,那么下面 + 的对齐就是 ~(16 - 1) ,也就是 1111xxx0000, 这样就可以进行相应的对齐 + +(加上)一个 (pageNo -1)的原因是 可以让首地址在 前面的范畴内 + */ return((void*)((((ulint) ptr) + align_no - 1) & ~(align_no - 1))); } diff --git a/storage/innobase/include/ut0list.h b/storage/innobase/include/ut0list.h index 29fc8669ce4..c5cc5547318 100644 --- a/storage/innobase/include/ut0list.h +++ b/storage/innobase/include/ut0list.h @@ -151,6 +151,10 @@ ib_list_is_empty( const ib_list_t* list); /* in: list */ /* List. */ +/** + * wangyang @@@ mysql 定义的双向链表 + * 这里的双向链表 只是一个 简单的链表 并不能实现线程安全 + */ struct ib_list_t { ib_list_node_t* first; /*!< first node */ ib_list_node_t* last; /*!< last node */ @@ -159,6 +163,9 @@ struct ib_list_t { }; /* A list node. */ +/** + * wangyang @@双向链表节点 + */ struct ib_list_node_t { ib_list_node_t* prev; /*!< previous node */ ib_list_node_t* next; /*!< next node */ diff --git a/storage/innobase/include/ut0lst.h b/storage/innobase/include/ut0lst.h index b53e7ade4c1..e42cbf69cbf 100644 --- a/storage/innobase/include/ut0lst.h +++ b/storage/innobase/include/ut0lst.h @@ -92,6 +92,9 @@ ut_elem_get_node(Type& elem, size_t offset) { ut_a(offset < sizeof(elem)); + /** + * wangyang reinterpret_cast用于 无关类型转换 + */ return(*reinterpret_cast*>( reinterpret_cast(&elem) + offset)); } @@ -119,11 +122,19 @@ ut_list_prepend( Type& elem, size_t offset) { + /** + * wangyang 这里的目的是 获取这个 elem 中的节点部分 + * 比如一个 ut_mem_block_list 中获取 相应的 这个 offset + * 找到相应的位置 + */ ut_list_node& elem_node = ut_elem_get_node(elem, offset); elem_node.prev = 0; elem_node.next = list.start; + /** + * 让之前的 start 节点的prev 指向 上面新加入过来的节点 + */ if (list.start != 0) { ut_list_node& base_node = ut_elem_get_node(*list.start, offset); diff --git a/storage/innobase/include/ut0vec.h b/storage/innobase/include/ut0vec.h index 432fb348a09..b7be6251cdb 100644 --- a/storage/innobase/include/ut0vec.h +++ b/storage/innobase/include/ut0vec.h @@ -311,17 +311,24 @@ ib_ut_allocator_free( ib_alloc_t* ib_ut_alloc); /* in: alloc instace to free */ /* Allocator used by ib_vector_t. */ +/** + * wangyang @@ + */ struct ib_alloc_t { - ib_mem_alloc_t mem_malloc; /* For allocating memory */ - ib_mem_free_t mem_release; /* For freeing memory */ - ib_mem_resize_t mem_resize; /* For resizing memory */ - void* arg; /* Currently if not NULL then it + //对应的 函数指针 是在声明的时候 在进行一个声明 + ib_mem_alloc_t mem_malloc; /* For allocating memory */ ////分配器的malloc函数指针 + ib_mem_free_t mem_release; /* For freeing memory */ //分配器的free函数指针 + ib_mem_resize_t mem_resize; /* For resizing memory */ //分配器的重新定义堆大小指针 + void* arg; /* Currently if not NULL then it //堆句柄,如果是系统的malloc方式,这个值为NULL points to the heap instance */ }; /* See comment at beginning of file. */ +/** + * wangyang 这里是 mysql 自定义 verctor + */ struct ib_vector_t { - ib_alloc_t* allocator; /* Allocator, because one size + ib_alloc_t* allocator; /* Allocator, because one size 使用 上面定义的 ib_alloc_t进行分配一块内存 doesn't fit all */ void* data; /* data elements */ ulint used; /* number of elements currently used */ diff --git a/storage/innobase/include/ut0wqueue.h b/storage/innobase/include/ut0wqueue.h index 33385ddf2d4..0138f9c78d4 100644 --- a/storage/innobase/include/ut0wqueue.h +++ b/storage/innobase/include/ut0wqueue.h @@ -96,9 +96,14 @@ ib_wqueue_timedwait( ib_time_t wait_in_usecs); /* in: wait time in micro seconds */ /* Work queue. */ +/** + * wangyang @@ mysql 实现的 fifo队列 (阻塞队列) + * + * os_event_t 用于进行 通知,比如放入之后 通知消费者 + */ struct ib_wqueue_t { - ib_mutex_t mutex; /*!< mutex protecting everything */ - ib_list_t* items; /*!< work item list */ + ib_mutex_t mutex; /*!< mutex protecting everything */ // 互斥信号量 + ib_list_t* items; /*!< work item list */ //使用list 作为队列载体 os_event_t event; /*!< event we use to signal additions to list */ }; diff --git a/storage/innobase/mem/mem0dbg.cc b/storage/innobase/mem/mem0dbg.cc index a77785a369a..2396cba7a1e 100644 --- a/storage/innobase/mem/mem0dbg.cc +++ b/storage/innobase/mem/mem0dbg.cc @@ -142,6 +142,21 @@ mem_field_trailer_get_check(byte* field) #ifndef UNIV_HOTBACKUP /******************************************************************//** Initializes the memory system. */ +/** + * wangyang 这个函数说的 很清楚,用于初始 innodb 内存系统 + */ + /* + innodb_additional_mem_pool_size 是 InnoDB 用来保存数据字典信息和其他内部数据结构的内存池的大小,单位是 byte,参数默认值为8M。数据库中的表数量越多,参数值应该越大,如果 InnoDB 用完了内存池中的内存,就会从操作系统中分配内存,同时在 error log 中打入报警信息。 + +innodb_use_sys_malloc 配置为 ON 时,innodb_additional_mem_pool_size 失效(直接从操作系统分配内存)。 + +innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 在 MySQL 5.7.4 中移除。 + + + 早期操作系统的内存分配器性能和可伸缩性较差,并且当时没有适合多核心CPU的内存分配器。所以,InnoDB 实现了一套自己的内存分配系统,做为内存系统的参数之一,引入了innodb_additional_mem_pool_size。 +随着多核心CPU的广泛应用和操作系统的成熟,操作系统能够提供性能更高、可伸缩性更好的内存分配器,包括 Hoard、libumem、mtmalloc、ptmalloc、tbbmalloc 和 TCMalloc 等。InnoDB 实现的内存分配器相比操作系统的内存分配器并没有明显优势,所以在之后的版本,会移除 innodb_additional_mem_pool_size 和 innodb_use_sys_malloc 两个参数,统一使用操作系统的内存分配器。 + + */ UNIV_INTERN void mem_init( @@ -174,7 +189,10 @@ mem_init( size = 1; } - mem_comm_pool = mem_pool_create(size); + /** + * wangyang @@@ 这里用于创建 内存池 + */ + mem_comm_pool = mem_pool_create(size); //这里创建 公共内存池 } /******************************************************************//** diff --git a/storage/innobase/mem/mem0mem.cc b/storage/innobase/mem/mem0mem.cc index e066aff5b30..68b15ae227f 100644 --- a/storage/innobase/mem/mem0mem.cc +++ b/storage/innobase/mem/mem0mem.cc @@ -328,16 +328,23 @@ mem_heap_create_block_func( len = MEM_BLOCK_HEADER_SIZE + MEM_SPACE_NEEDED(n); #ifndef UNIV_HOTBACKUP + /** + * wangyang @@ 下面要根据 type 的方式 进行判断 使用何种方式 进行切分内存 + * 类型是 dynamic 或者 长度 小于 1/2 Page + */ if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { ut_ad(type == MEM_HEAP_DYNAMIC || n <= MEM_MAX_ALLOC_IN_BUF); + /** + * wangyang @@@ 这里可以看到 mem_block_t 是从 mem_area 进行分离出来的 + */ block = static_cast( mem_area_alloc(&len, mem_comm_pool)); } else { len = UNIV_PAGE_SIZE; - if ((type & MEM_HEAP_BTR_SEARCH) && heap) { + if ((type & MEM_HEAP_BTR_SEARCH) && heap) { //wangyang @@ 这种情况下 首先是 符合这种type 然后是 heap 必须存在 /* We cannot allocate the block from the buffer pool, but must get the free block from the heap header free block field */ @@ -350,7 +357,7 @@ mem_heap_create_block_func( return(NULL); } } else { - buf_block = buf_block_alloc(NULL); + buf_block = buf_block_alloc(NULL); // wangyang @@ 这种情况下 会从 buf_pool 中进行分配 } block = (mem_block_t*) buf_block->frame; diff --git a/storage/innobase/mem/mem0pool.cc b/storage/innobase/mem/mem0pool.cc index fe9a84d21fa..2926d398acd 100644 --- a/storage/innobase/mem/mem0pool.cc +++ b/storage/innobase/mem/mem0pool.cc @@ -100,12 +100,31 @@ pool, and after that its locks will grow into the buffer pool. */ /** Data structure for a memory pool. The space is allocated using the buddy algorithm, where free list i contains areas of size 2 to power i. */ +/** + * wangyang @@ 创建一个内存池 作为 mem_pool_t 去使用 + */ struct mem_pool_t{ byte* buf; /*!< memory pool */ ulint size; /*!< memory common pool size */ ulint reserved; /*!< amount of currently allocated memory */ ib_mutex_t mutex; /*!< mutex protecting this struct */ + /** + * mem_pool_t 的free_list是 基础节点, 也可以看做是 + * ut_list_node的控制节点,用于表明比如 list有多少 节点 + * start 起始节点 + * end 尾部节点 + */ + /* + struct ut_list_base { + typedef TYPE elem_type; + ulint count; !< count of nodes in list + TYPE* start; !< pointer to list start, NULL if empty + TYPE* end; !< pointer to list end, NULL if empty +}; + + +*/ UT_LIST_BASE_NODE_T(mem_area_t) free_list[64]; /*!< lists of free memory areas: an area is put to the list whose number @@ -226,11 +245,19 @@ mem_pool_create( ulint i; ulint used; + /** + * wangyang 这里 malloc 分配了一个 mem_pool_t 对象 + */ pool = static_cast(ut_malloc(sizeof(mem_pool_t))); + /** + * 这里的分配 是 + */ pool->buf = static_cast(ut_malloc_low(size, TRUE)); pool->size = size; + //wangyang @ 用于创建 一个 mutex 对象 + // mem_pool_mutex_key 对应的 对应的值 mem_pool_mutex ,用于对应 mutex 的名称 mutex_create(mem_pool_mutex_key, &pool->mutex, SYNC_MEM_POOL); /* Initialize the free lists */ diff --git a/storage/innobase/os/os0proc.cc b/storage/innobase/os/os0proc.cc index ff6d65e4ae6..db19827b86c 100644 --- a/storage/innobase/os/os0proc.cc +++ b/storage/innobase/os/os0proc.cc @@ -154,6 +154,7 @@ os_mem_alloc_large( /* Align block size to system page size */ ut_ad(ut_is_2pow(size)); size = *n = ut_2pow_round(*n + (size - 1), size); + //wangyang @@@ 这里会使用 mmap 进行分配 ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | OS_MAP_ANON, -1, 0); if (UNIV_UNLIKELY(ptr == (void*) -1)) { diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 21ac1aeee62..8afb45b79cc 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -1038,7 +1038,11 @@ srv_general_init(void) recv_sys_var_init(); os_sync_init(); sync_init(); - mem_init(srv_mem_pool_size); + /** + * wangyang @@ 这里初始化的是 mem_pool 跟 buf_pool 是不一样的,初始化 用的是 malloc + * srv_mem_pool_size = innobase_additional_mem_pool_size + */ + mem_init(srv_mem_pool_size); //wangyang @@ 内存池初始化 innodb内存 系统的初始化 que_init(); row_mysql_init(); } @@ -1085,6 +1089,9 @@ srv_boot(void) /* Initialize synchronization primitives, memory management, and thread local storage */ + /** + * wangyang @@ 该方法里面 会进行整体初始化 包括 内存系统的初始化 + */ srv_general_init(); /* Initialize this module */ diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 25a27b701ce..48c1f6d25d0 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -1849,6 +1849,9 @@ innobase_start_or_create_for_mysql(void) srv_buf_pool_instances = 1; } + /** + * wangyang @@ innobase 启动 + */ srv_boot(); ib_logf(IB_LOG_LEVEL_INFO, @@ -1975,6 +1978,10 @@ innobase_start_or_create_for_mysql(void) ib_logf(IB_LOG_LEVEL_INFO, "Initializing buffer pool, size = %.1f%c", size, unit); + //wangyang @@ 这里会创建 buf pool 以及 buf pool instances + /** + * 这里的初始化 是初始化 buf_pool 这里面使用的都是 使用 mmap + */ err = buf_pool_init(srv_buf_pool_size, srv_buf_pool_instances); if (err != DB_SUCCESS) { diff --git a/storage/innobase/ut/ut0mem.cc b/storage/innobase/ut/ut0mem.cc index 2bb5d9ce332..987844f8c19 100644 --- a/storage/innobase/ut/ut0mem.cc +++ b/storage/innobase/ut/ut0mem.cc @@ -114,6 +114,9 @@ ut_malloc_low( retry: os_fast_mutex_lock(&ut_list_mutex); + /** + * wangyang 这里通过 malloc 分配内存 + */ ret = malloc(n + sizeof(ut_mem_block_t)); if (ret == NULL && retry_count < 60) { @@ -192,6 +195,10 @@ ut_malloc_low( ut_total_allocated_memory += n + sizeof(ut_mem_block_t); + /** + * wangyang 这里的目的是 将新创建出的 ret 节点添加到 ut_mem_block_list 这个链表中,是一个全局 静态链表 + * 第一个参数是 name 第二个参数是 实际对应的 list 第三个参数是一个指针 + */ UT_LIST_ADD_FIRST(mem_block_list, ut_mem_block_list, ((ut_mem_block_t*) ret)); os_fast_mutex_unlock(&ut_list_mutex); diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c index 8838aa7e4f4..ffbf72ed1b7 100644 --- a/strings/ctype-big5.c +++ b/strings/ctype-big5.c @@ -6832,6 +6832,9 @@ size_t my_well_formed_len_big5(const CHARSET_INFO *cs MY_ATTRIBUTE((unused)), } +/** + * wangyang + */ static MY_COLLATION_HANDLER my_collation_big5_chinese_ci_handler = { NULL, /* init */ diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index faac2c94335..8b72249e947 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -677,6 +677,10 @@ my_strcasecmp_mb_bin(const CHARSET_INFO *cs MY_ATTRIBUTE((unused)), } +/** + * + wangyang ** 这里设置 hash_sort 函数 + */ void my_hash_sort_mb_bin(const CHARSET_INFO *cs MY_ATTRIBUTE((unused)), const uchar *key, size_t len,ulong *nr1, ulong *nr2) diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c index e4d1faa2a8f..c1cd2e3c545 100644 --- a/strings/ctype-utf8.c +++ b/strings/ctype-utf8.c @@ -6089,6 +6089,9 @@ static MY_COLLATION_HANDLER my_collation_utf8_general_ci_handler = }; +/** + * wangyang *** 杩欓噷浼氳缃 hash_sort 鍑芥暟 + */ static MY_COLLATION_HANDLER my_collation_utf8_bin_handler = { NULL, /* init */ @@ -6100,7 +6103,7 @@ static MY_COLLATION_HANDLER my_collation_utf8_bin_handler = my_wildcmp_mb_bin, my_strcasecmp_mb_bin, my_instr_mb, - my_hash_sort_mb_bin, + my_hash_sort_mb_bin, //wangyang *** 杩欓噷璁剧疆 hash_sort鍑芥暟 my_propagate_simple }; From 1865020c586c7acf03948a4fa49b693391d98572 Mon Sep 17 00:00:00 2001 From: wangy102 <31234273+simake2017@users.noreply.github.com> Date: Sat, 17 Jul 2021 10:49:36 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=86=85=E5=AD=98=E9=83=A8=E5=88=86?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 34 ++---------------- include/my_alloc.h | 5 +++ mysys/my_alloc.c | 53 ++++++++++++++++++++++++---- mysys/my_malloc.c | 3 ++ sql/sql_base.cc | 5 +++ sql/table.cc | 38 ++++++++++++++++---- sql/table.h | 3 ++ sql/table_cache.h | 20 +++++++++++ sql/thr_malloc.cc | 3 ++ storage/innobase/dict/dict0boot.cc | 10 ++++++ storage/innobase/dict/dict0dict.cc | 8 +++++ storage/innobase/dict/dict0mem.cc | 4 +++ storage/innobase/include/dict0mem.h | 3 ++ storage/innobase/include/hash0hash.h | 10 ++++++ storage/innobase/include/mem0mem.h | 5 ++- storage/innobase/include/os0sync.h | 21 +++++++++++ storage/innobase/mem/mem0pool.cc | 20 ++++++++++- storage/innobase/os/os0sync.cc | 23 ++++++++++++ storage/innobase/srv/srv0start.cc | 3 +- storage/innobase/ut/ut0mem.cc | 4 +++ 20 files changed, 227 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index e4201975eec..a49f0cf1ba6 100644 --- a/README.md +++ b/README.md @@ -1,33 +1,3 @@ -# AliSQL -AliSQL is a MySQL branch originated from Alibaba Group. It is based on the MySQL official release and has many feature and performance enhancements. AliSQL has proven to be very stable and efficient in production environment. It can be used as a free, fully compatible, enhanced and open source drop-in replacement for MySQL. +来自于 AliSql 进行中文注释 -AliSQL has been an open source project since August 2016. It is being actively developed by engineers from Alibaba Group. Moreover, it includes patches from Percona, WebScaleSQL, and MariaDB. AliSQL is a fruit of community effort. Everyone is welcomed to get involved. -# AliSQL Release Notes - -[Changes in AliSQL 5.6.32 (2018-05-01) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2018-05-01)) -[Changes in AliSQL 5.6.32 (2018-01-24) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2018-01-24)) -[Changes in AliSQL 5.6.32 (2017-10-10) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2017-10-10)) -[Changes in AliSQL 5.6.32 (2017-07-16) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2017-07-16)) -[Changes in AliSQL 5.6.32 (2017-05-04) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2017-05-04)) -[Changes in AliSQL 5.6.32 (2017-02-14) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2017-02-14)) -[Changes in AliSQL 5.6.32 (2016-12-25) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2016-12-25)) -[Changes in AliSQL 5.6.32 (2016-11-11) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2016-11-11)) -[Changes in AliSQL 5.6.32 (2016-10-14) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2016-10-14)) -[Changes in AliSQL 5.6.32 (2016-09-15) ](https://github.com/alibaba/AliSQL/wiki/Changes-in-AliSQL-5.6.32-(2016-09-15)) - -## AliSQL Compiler Guide -[AliSQL-Compiler-Guide](http://blog.fungo.me/2016/10/compile-alisql-from-source/) - -# AliSQL benchmark -[Performance benchmark ](https://github.com/alibaba/AliSQL/wiki/AliSQL-Performance-benchmark) -[Performance benchmark for inventory ](https://github.com/alibaba/AliSQL/wiki/AliSQL-Performance-benchmark-for-inventory) - -# AliSQL wiki -[Wiki](https://github.com/alibaba/AliSQL/wiki) - -# AliSQLBackup -[AliSQLBackup](https://github.com/alibaba/AliSQLBackup) -[AliSQLBackup.wiki](https://github.com/alibaba/AliSQLBackup/wiki) - -## AliSQL Sequence Engine -[AliSQL-Sequence-Doc](https://github.com/alibaba/AliSQL/wiki/AliSQL-Sequence-Doc_C) +annotation 分支 \ No newline at end of file diff --git a/include/my_alloc.h b/include/my_alloc.h index 9e2ef541b3c..729be64cc81 100644 --- a/include/my_alloc.h +++ b/include/my_alloc.h @@ -37,12 +37,17 @@ typedef struct st_used_mem typedef struct st_mem_root { + // 空闲内存 USED_MEM *free; /* blocks with free memory in it */ + //已使用内存 USED_MEM *used; /* blocks almost without free memory */ + //预分配内存 USED_MEM *pre_alloc; /* preallocated block */ /* if block have less memory it will be put in 'used' list */ size_t min_malloc; + //初始化 block_size 默认 1024 size_t block_size; /* initial block size */ + // 已分配的 block 数量 unsigned int block_num; /* allocated blocks counter */ /* first free block in queue test counter (if it exceed diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index a5209835332..d1a0ccbc7b6 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -55,6 +55,12 @@ static void update_query_size(MEM_ROOT *root, size_t length, int flag) reported as error in first alloc_root() on this memory root. */ +/** + * + wangyang 这里的目的是初始化 mem_root 对象 , 前面传递过来的是一个空结构体, + 下面会对内存部分 进行相应的初始化 + + */ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, size_t pre_alloc_size MY_ATTRIBUTE((unused))) { @@ -69,6 +75,9 @@ void init_alloc_root(MEM_ROOT *mem_root, size_t block_size, mem_root->first_block_usage= 0; #if !(defined(HAVE_purify) && defined(EXTRA_DEBUG)) + /** + * wangyang 下面这一块 表示一定的预分配 + */ if (pre_alloc_size) { if ((mem_root->free= mem_root->pre_alloc= @@ -220,20 +229,28 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) mem_root->first_block_usage++ >= ALLOC_MAX_BLOCK_USAGE_BEFORE_DROP && (*prev)->left < ALLOC_MAX_BLOCK_TO_DROP) { + /** + * wangyang 如果 剩余 已经少于length 那么移除 free list 中 + * 移入到 used 列表当中 + */ next= *prev; *prev= next->next; /* Remove block from list */ next->next= mem_root->used; mem_root->used= next; mem_root->first_block_usage= 0; } + /** + * wangyang 这里会按照 free 指针进行寻找,直到找到 left > length 的内存块 + */ for (next= *prev ; next && next->left < length ; next= next->next) prev= &next->next; } if (! next) { /* Time to alloc new block */ + // block_nun = 4 >> 2 ==> 1 block_size= mem_root->block_size * (mem_root->block_num >> 2); get_size= length+ALIGN_SIZE(sizeof(USED_MEM)); - get_size= MY_MAX(get_size, block_size); + get_size= MY_MAX(get_size, block_size); // wangyang @@ 这里会 比较 获取 最大的值 if (!(next = (USED_MEM*) my_malloc(get_size,MYF(MY_WME | ME_FATALERROR)))) { @@ -241,16 +258,26 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) (*mem_root->error_handler)(); DBUG_RETURN((void*) 0); /* purecov: inspected */ } + /** + * wangyang prev 指针 表示的是 free 指针 + * 这里主要是将 新增加的 内存块 放置在 最前面 + */ update_query_size(mem_root, length, 1); - mem_root->block_num++; + mem_root->block_num++; // 分配的块的数量 增加 next->next= *prev; - next->size= get_size; + next->size= get_size; // next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); *prev=next; } + /** + * wangyang 这里会 确保 + */ point= (uchar*) ((char*) next+ (next->size-next->left)); /*TODO: next part may be unneded due to mem_root->first_block_usage counter*/ + /** + * wangyang 这里会判断 ,如果 剩余 内存大小, 小于 最小分配大小,那么放入 used 链表当中 + */ if ((next->left-= length) < mem_root->min_malloc) { /* Full block */ *prev= next->next; /* Remove block from list */ @@ -290,12 +317,20 @@ void *multi_alloc_root(MEM_ROOT *root, ...) size_t tot_length, length; DBUG_ENTER("multi_alloc_root"); + /** + * va_start 在使用的时候 第一个参数是 va_list , 用于承载所有的 变长参数 + * 第二个参数是 变长参数前最后一个 参数,用于确认分界 + */ va_start(args, root); tot_length= 0; - while ((ptr= va_arg(args, char **))) + /** + * wangyang 使用 va_arg 的作用是 用于从 va_list 中获取 某个参数 + * + */ + while ((ptr= va_arg(args, char **))) //这里的目的是从va_list中获取一个参数,类型是 char** 类型 { - length= va_arg(args, uint); - tot_length+= ALIGN_SIZE(length); + length= va_arg(args, uint); // 这里是从va_list中获取参数,类型是uint 目的是用于确认相应的大小(内存大小) + tot_length+= ALIGN_SIZE(length);// 这里对总的内存大小进行累加 } va_end(args); @@ -304,11 +339,15 @@ void *multi_alloc_root(MEM_ROOT *root, ...) va_start(args, root); res= start; + /* + * 这里的目的是用来 给相应的指针分配地址 ,ptr是二级指针 + * 然后使用 *ptr 来确认 分配的 地址 + */ while ((ptr= va_arg(args, char **))) { *ptr= res; length= va_arg(args, uint); - res+= ALIGN_SIZE(length); + res+= ALIGN_SIZE(length); // 这里用于对齐内存 } va_end(args); DBUG_RETURN((void*) start); diff --git a/mysys/my_malloc.c b/mysys/my_malloc.c index 871c735e343..0446a6f5f39 100644 --- a/mysys/my_malloc.c +++ b/mysys/my_malloc.c @@ -77,6 +77,9 @@ void *my_malloc(size_t size, myf my_flags) } else { + /** + * 用于更新 全局 malloc 内存 + */ update_malloc_size(_msize(point)); DBUG_EXECUTE_IF("simulate_out_of_memory", { diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 353299b08dd..4bd4b22867d 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -488,6 +488,7 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, MDL_SHARED)); /* Read table definition from cache */ + //wangyang @@ 如果这里面已经存在了,那么就可以直接返回 if ((share= (TABLE_SHARE*) my_hash_search_using_hash_value(&table_def_cache, hash_value, (uchar*) key, key_length))) goto found; @@ -512,6 +513,10 @@ TABLE_SHARE *get_table_share(THD *thd, TABLE_LIST *table_list, */ assign_new_table_id(share); + /** + * wangyang @@ 这里主要是向table_def_cache 中插入相应的 表信息 + * + */ if (my_hash_insert(&table_def_cache, (uchar*) share)) { free_table_share(share); diff --git a/sql/table.cc b/sql/table.cc index 4c6ab0d906a..8c2e901048e 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -320,8 +320,8 @@ TABLE_CATEGORY get_table_category(const LEX_STRING *db, const LEX_STRING *name) TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, const char *key, uint key_length) { - MEM_ROOT mem_root; - TABLE_SHARE *share; + MEM_ROOT mem_root; //wangyang 结构体 初始化 是一个空的对象, 而不是 NULL + TABLE_SHARE *share; //这里初始分配的 地址不能使用 char *key_buff, *path_buff; char path[FN_REFLEN]; uint path_length; @@ -333,15 +333,31 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, const char *key, path_length= build_table_filename(path, sizeof(path) - 1, table_list->db, table_list->table_name, "", 0); + /** + * wangyang @@@ table_share 函数这里会初始化 mem_root + * 初始化 mem_root + */ init_sql_alloc(&mem_root, TABLE_ALLOC_BLOCK_SIZE, 0); + /** + * wangyang 在这里进行 变量初始化,就是调用下面的方法 + * 下面方法的作用是 相应的指针进行初始化, 可以看到方法名字子 多重初始化 ,第一个参数是指针, + * 第二个参数是 对应的内存的大小 + */ if (multi_alloc_root(&mem_root, - &share, sizeof(*share), - &key_buff, key_length, - &path_buff, path_length + 1, + &share, sizeof(*share), //share 是表示 table_share 对象 + &key_buff, key_length, // key_buf 是表示 key(表示一张表的key) 的长度 + &path_buff, path_length + 1, // 表示 表的路径信息 &cache_element_array, table_cache_instances * sizeof(*cache_element_array), NULL)) { + + /* + # include +void *memset(void *s, int c, unsigned long n); +函数的功能是:将指针变量 s 所指向的前 n 字节的内存单元用一个“整数” c 替换,注意 c 是 int 型。s 是 void* 型的指针变量,所以它可以为任何类型的数据进行初始化。 + */ + //这里的作用是 将 share 指针指向的 内存全部初始化为0 memset(share, 0, sizeof(*share)); share->set_table_cache_key(key_buff, key, key_length); @@ -366,10 +382,20 @@ TABLE_SHARE *alloc_table_share(TABLE_LIST *table_list, const char *key, share->m_flush_tickets.empty(); + /** + * 这里用于初始化 cache_element_array 地址对应的内存,长度为 len + * 全部初始化为0 + */ memset(cache_element_array, 0, table_cache_instances * sizeof(*cache_element_array)); share->cache_element= cache_element_array; + /** + * wangyang 从 第二个参数指向的内存 指向 第一个参数指向的内存 + * + * 内存拷贝 将 局部变量 &mem_root 对应的内存 复制到 share 中对应的 mem_root中 + * 对应的地址 share 中 mem_root 是结构体,零值不是null , 而是 空结构体 + */ memcpy((char*) &share->mem_root, (char*) &mem_root, sizeof(mem_root)); mysql_mutex_init(key_TABLE_SHARE_LOCK_ha_data, &share->LOCK_ha_data, MY_MUTEX_INIT_FAST); @@ -851,7 +877,7 @@ int open_table_def(THD *thd, TABLE_SHARE *share, uint db_flags) root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC); old_root= *root_ptr; *root_ptr= &share->mem_root; - error= open_binary_frm(thd, share, head, file); + error= open_binary_frm(thd, share, head, file); //wangyang @@@ 这里会打开二进制文件 ,并初始化 table_share 对象 *root_ptr= old_root; error_given= 1; } diff --git a/sql/table.h b/sql/table.h index 11d3d214d9f..e7e48497033 100644 --- a/sql/table.h +++ b/sql/table.h @@ -586,6 +586,9 @@ struct TABLE_SHARE{ TABLE_SHARE() {} /* Remove gcc warning */ /** Category of this table. */ + /* + * 枚举 类型 用于声明 表的种类 + */ TABLE_CATEGORY table_category; /* hash of field names (contains pointers to elements of field array) */ diff --git a/sql/table_cache.h b/sql/table_cache.h index 00a11c5e3fa..4644dd411cd 100644 --- a/sql/table_cache.h +++ b/sql/table_cache.h @@ -35,6 +35,21 @@ This significantly increases scalability in some scenarios. */ +/* + + MySQL 5.6后,引入了“table_cache_instances”参数来控制 table cache instance的个数。目前最大值是64,默认值是1。建议值是16,当系统CPU核数高于16时。引入此参数的目的是,提高并发。相当于把table cache 拆成了多个分区,每个分区的打开table句柄数为:table_open_cache / table_open_cache_instances。跟innodb_buffer_pool_instances参数有异曲同工的作用。 + table_cache_instances的最大值为64,每个thread会使用哪个table cache instance,根据thread id取模得到:m_table_cache [thread_id % table_cache_instances]。其中m_table_cache是table cache的instance 分区数组。源码定义如下: + + Table cache instance统一由Table_cache_manager类来管理。Table_cache_manager负责初始化和销毁table cache instance。 + 另外,取代LOCK_open锁的是64个m_lock mutex。因此大大降低了table cache 锁的争用,将其分摊到了64个instance上的m_lock mutex上。 + 但是涉及到多个table cache中的对象的DDL语句,仍然需要整个table cache级别的锁,即Lock_open。另外,对所有table cache instances以及table definition cache上锁时,也需持有Lock_open锁。 + + + table_cache 的目的是 在使用的时候用于提高并发,比如 某个线程中 在使用的时候, 可以从 table_cache_manager 中 + 获取对应的 table_cache 信息,然后在找到 对应的 table_share,用于提高并发 + + */ + class Table_cache { private: @@ -70,6 +85,11 @@ class Table_cache of used TABLE objects in this table cache is stored. We use Table_cache_element::share::table_cache_key as key for this hash. */ + + /* + * 这里说的也很清楚,里面存储的是 table_cache_element 对象, table_share 用于表示一个表对象 + * 其他 + */ HASH m_cache; /** diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc index e5b13fff543..96c9b45dfd2 100644 --- a/sql/thr_malloc.cc +++ b/sql/thr_malloc.cc @@ -28,6 +28,9 @@ using std::max; extern "C" void sql_alloc_error_handler(void); +/* + * wangyang @@@ 初始化 这里的作用 初始化 mem_root 结构体,并不一定会 分配内存 + */ void init_sql_alloc(MEM_ROOT *mem_root, uint block_size, uint pre_alloc) { init_alloc_root(mem_root, block_size, pre_alloc); diff --git a/storage/innobase/dict/dict0boot.cc b/storage/innobase/dict/dict0boot.cc index 94a3af2852b..d0cce0d9e7a 100644 --- a/storage/innobase/dict/dict0boot.cc +++ b/storage/innobase/dict/dict0boot.cc @@ -243,6 +243,10 @@ dict_hdr_create( Initializes the data dictionary memory structures when the database is started. This function is also called when the data dictionary is created. @return DB_SUCCESS or error code. */ +/** + * wangyang 初始化数据 字典内存结构 + + */ UNIV_INTERN dberr_t dict_boot(void) @@ -276,6 +280,9 @@ dict_boot(void) mtr_start(&mtr); /* Create the hash tables etc. */ + /** + * wangyang @@@ 这里是创建相应的 目录表 + */ dict_init(); heap = mem_heap_create(450); @@ -302,6 +309,9 @@ dict_boot(void) /* Insert into the dictionary cache the descriptions of the basic system tables */ /*-------------------------*/ + /** + * wangyang 创建相应的系统表 + */ table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, 0, 0); dict_mem_table_add_col(table, heap, "NAME", DATA_BINARY, 0, 0); diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 1c9da17cbc0..f10a7145d03 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -1086,6 +1086,7 @@ void dict_init(void) /*===========*/ { + //wangyang @@@ dict_sys 鍒濆鍖 dict_sys = static_cast(mem_zalloc(sizeof(*dict_sys))); mutex_create(dict_sys_mutex_key, &dict_sys->mutex, SYNC_DICT); @@ -1340,6 +1341,13 @@ dict_table_add_to_cache( } /* Add table to hash table of tables */ + /** + * wangyang 绗笁涓弬鏁 table_hash 鏄痟ash 琛 , 杩欓噷浼氭彃鍏ュ埌 + * hash_table 褰撲腑 + * + * 杩欓噷鐨勫姛鑳芥槸 灏 table 淇℃伅 鎻掑叆鍒 table_hash 閲岄潰鍘 + * + */ HASH_INSERT(dict_table_t, name_hash, dict_sys->table_hash, fold, table); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 4d0e0d49259..9259e654c44 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -80,6 +80,10 @@ dict_mem_table_create( ut_a(dict_tf_is_valid(flags)); ut_a(!(flags2 & ~DICT_TF2_BIT_MASK)); + /** + * wangyang @@ 从这里可以看出 mem_heap_create就是 用于普通情况下的内存分配,普通时候 + * 使用的内存用的都是 mem_heap_create函数 + */ heap = mem_heap_create(DICT_HEAP_SIZE); table = static_cast( diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 6f5643a50d2..1ea935d38e6 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -920,6 +920,9 @@ the table, DML from memcached will be blocked. */ /** Data structure for a database table. Most fields will be initialized to 0, NULL or FALSE in dict_mem_table_create(). */ +/** + * wangyang @@ 数据库表的 数据结构,用于存储相应的 + */ struct dict_table_t{ diff --git a/storage/innobase/include/hash0hash.h b/storage/innobase/include/hash0hash.h index 6f9a628df5d..0cf5a75b3e7 100644 --- a/storage/innobase/include/hash0hash.h +++ b/storage/innobase/include/hash0hash.h @@ -119,6 +119,14 @@ Assert that the mutex for the table is held */ /*******************************************************************//** Inserts a struct to a hash table. */ +/** + * wangyang Type 表示类型 Table 表示 hash 结构 + * fold 表示相应的hash 值 data 是要插入的数据 + * name 是相应的名称,代表相应节点的指针变量 + * + * + * + */ #define HASH_INSERT(TYPE, NAME, TABLE, FOLD, DATA)\ do {\ hash_cell_t* cell3333;\ @@ -143,6 +151,8 @@ do {\ struct3333->NAME = DATA;\ }\ } while (0) +//wangyang 这里struct3333 代表相应的 hash 表中的节点, 获取 node +// 表示相应的 节点信息,然后设置相应的 data 信息 #ifdef UNIV_HASH_DEBUG # define HASH_ASSERT_VALID(DATA) ut_a((void*) (DATA) != (void*) -1) diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index 8a74392b618..0bbdadc268a 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -387,8 +387,8 @@ mem_validate_all_blocks(void); * 里面会有 mem_block_t 形成链表 , mem_block_t 就是 mem_block_info_t * block 的内存 来源于 mem_pool (mem_pool 形成类似 buddy的分配方式) * - * 1、 * + * mem_block 是 链表的方式进行管理,但是 大小并不确定 * * */ @@ -416,6 +416,9 @@ struct mem_block_info_t { */ ulint free; /*!< offset in bytes of the first free position for user data in the block */ + /** + * 内存block的起始地址 + */ ulint start; /*!< the value of the struct field 'free' at the creation of the block */ #ifndef UNIV_HOTBACKUP diff --git a/storage/innobase/include/os0sync.h b/storage/innobase/include/os0sync.h index 367c2a31924..4b16a074d08 100644 --- a/storage/innobase/include/os0sync.h +++ b/storage/innobase/include/os0sync.h @@ -83,9 +83,22 @@ struct os_fast_mutex_t { }; /** Operating system event handle */ +/** + * wangyang 用于声明 信号量 + */ typedef struct os_event* os_event_t; /** An asynchronous signal sent between threads */ +/* + * wangyang 这里说的很清楚, 是用于两个线程之前的 进行 信号量 发送的线程 + * + * 这里的信号量 主要是 用于两个线程之间的通知 并不是常见的多个线程 + * + * 主要方法 os_event_create os_event_set os_event_reset + * 每次reset 之后 都会让 signal_count 数量增加, + * 所以signal_count 表示的是 重置次数,而不是 等待通知的数量 + * + */ struct os_event { #ifdef __WIN__ HANDLE handle; /*!< kernel event object, slow, @@ -97,10 +110,18 @@ struct os_event { in the signaled state, i.e., a thread does not stop if it tries to wait for this event */ + /** + * wangyang + */ ib_int64_t signal_count; /*!< this is incremented each time the event becomes signaled */ os_cond_t cond_var; /*!< condition variable is used in waiting for the event */ + + /** + * wangyang ut_list_node_t 是一个 节点列表 , 使用相应的宏定义 + * 每个节点 表示一个链表中的节点, 有prev 和 next + */ UT_LIST_NODE_T(os_event_t) os_event_list; /*!< list of all created events */ }; diff --git a/storage/innobase/mem/mem0pool.cc b/storage/innobase/mem/mem0pool.cc index 2926d398acd..26d61c329f9 100644 --- a/storage/innobase/mem/mem0pool.cc +++ b/storage/innobase/mem/mem0pool.cc @@ -231,6 +231,14 @@ mem_area_set_free( | free; } +/* + * + 基础内存管理的方法如下: + ut_malloc_low 分配一个n长度的内存块,并将分配的块记录到ut_mem_block_list当中. + ut_malloc 与ut_malloc_low功能相同,但是会用0初始化所分配的内存。 + ut_free 释放一个分配的内存块,并将其从ut_mem_block_list当中删除。 + ut_free_all_mem 释放ut_mem_block_list所有的内存块并清空ut_mem_block_list + */ /********************************************************************//** Creates a memory pool. @return memory pool */ @@ -251,7 +259,11 @@ mem_pool_create( pool = static_cast(ut_malloc(sizeof(mem_pool_t))); /** - * 这里的分配 是 + * + * wangyang 这里 使用的是 os malloc 分配的一整块内存, + * 并没有使用 相应的内存管理技术 ,就是一整块单独的内存 + * 然后加入到 链表当中 + * */ pool->buf = static_cast(ut_malloc_low(size, TRUE)); pool->size = size; @@ -386,6 +398,12 @@ mem_pool_fill_free_list( Allocates memory from a pool. NOTE: This low-level function should only be used in mem0mem.*! @return own: allocated memory buffer */ +/** + * + wangyang @@@ 从 common_pool当中 分配内存 , mem_heap_t 也是从这里面分配的内存 + mem_heap_t 是 block 链表的内存管理方式 + mem_pool_t 是 buddy 的分配方式,分配block + */ UNIV_INTERN void* mem_area_alloc( diff --git a/storage/innobase/os/os0sync.cc b/storage/innobase/os/os0sync.cc index cd57abd0623..955e8534d2b 100644 --- a/storage/innobase/os/os0sync.cc +++ b/storage/innobase/os/os0sync.cc @@ -125,6 +125,9 @@ os_cond_init( ut_a(initialize_condition_variable != NULL); initialize_condition_variable(cond); #else + /** + * wangyang 这里用于初始化 cond 结构体 + */ ut_a(pthread_cond_init(cond, NULL) == 0); #endif } @@ -369,6 +372,8 @@ os_event_create(void) { event = static_cast(ut_malloc(sizeof *event)); +// os_event_wait_low(event,) + #ifndef PFS_SKIP_EVENT_MUTEX os_fast_mutex_init(event_os_mutex_key, &event->os_mutex); #else @@ -446,6 +451,10 @@ that this thread should not wait in case of an intervening call to os_event_set() between this os_event_reset() and the os_event_wait_low() call. See comments for os_event_wait_low(). @return current signal_count. */ +/** + + wangyang reset + */ UNIV_INTERN ib_int64_t os_event_reset( @@ -584,10 +593,18 @@ os_event_wait_low( os_fast_mutex_lock(&event->os_mutex); + /** + * wangyang 如果这里 reset_sig_count 是0的话么,那么就会重新赋值为 相应的信号数量 + */ if (!reset_sig_count) { reset_sig_count = event->signal_count; } + + + /** + * wangyang 下面这里就是 信号量的等待,这里可以用于等待 相应的条件完成 + */ while (!event->is_set && event->signal_count == reset_sig_count) { os_cond_wait(&(event->cond_var), &(event->os_mutex)); @@ -825,6 +842,12 @@ os_fast_mutex_init_func( InitializeCriticalSection((LPCRITICAL_SECTION) fast_mutex); #else + /** + * wangyang 这里使用 pthread_mutex , 对 fast_mutex 进行初始化 + */ + +// pthread_mutex_lock(fast_mutex) + ut_a(0 == pthread_mutex_init(fast_mutex, MY_MUTEX_INIT_FAST)); #endif if (UNIV_LIKELY(os_sync_mutex_inited)) { diff --git a/storage/innobase/srv/srv0start.cc b/storage/innobase/srv/srv0start.cc index 48c1f6d25d0..107c4898b11 100644 --- a/storage/innobase/srv/srv0start.cc +++ b/storage/innobase/srv/srv0start.cc @@ -2453,7 +2453,8 @@ innobase_start_or_create_for_mysql(void) to access space 0, and the insert buffer at this stage already works for space 0. */ - err = dict_boot(); + + err = dict_boot(); //wangyang @@ 初始化 dict_table if (err != DB_SUCCESS) { return(err); diff --git a/storage/innobase/ut/ut0mem.cc b/storage/innobase/ut/ut0mem.cc index 987844f8c19..fa8d1eb58b5 100644 --- a/storage/innobase/ut/ut0mem.cc +++ b/storage/innobase/ut/ut0mem.cc @@ -88,6 +88,10 @@ ut_mem_init(void) /**********************************************************************//** Allocates memory. @return own: allocated memory */ + +/* + * wangyang ut_malloc_low 分配一个n长度的内存块,并将分配的块记录到ut_mem_block_list当中. + */ UNIV_INTERN void* ut_malloc_low(