欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

mysql InnoDB建表时设定初始大小的方法

程序员文章站 2024-02-25 17:14:09
innodb在写密集的压力时,由于b-tree扩展,因而也会带来数据文件的扩展,然而,innodb数据文件扩展需要使用mutex保护数据文件,这就会导致波动。 丁奇的博客说...

innodb在写密集的压力时,由于b-tree扩展,因而也会带来数据文件的扩展,然而,innodb数据文件扩展需要使用mutex保护数据文件,这就会导致波动。 丁奇的博客说明了这个问题:
when innodb under heavy write workload, datafiles will extend quickly, because of b-tree allocate new pages. but innodb need to use mutex to protect datafile, so it will cause performance jitter. xiaobin lin said this in his blog:
解决的方法也很简单,只要知道数据文件可能会增长到多大,预先扩展即可。阅读代码可以知道,innodb建表后自动初始化大小是fil_ibd_file_initial_size这个常量控制的,而初始化数据文件是由fil_create_new_single_table_tablespace()函数控制的。所以要改变数据文件初始化大小,只要修改fil_create_new_single_table_tablespace的传入值即可,默认是fil_ibd_file_initial_size。
how to solve it? that's easy. if we know the datafile will extend to which size at most, we can pre-extend it. after reading source code, we can know innodb initial datafile size by fil_ibd_file_initial_size, and fil_create_new_single_table_tablespace() function to do it. so if we want to change datafile initial size, we only need to change the initial size parameter in fil_create_new_single_table_tablespace(), the default value is fil_ibd_file_initial_size.
因此,我在建表语法中加上了datafile_initial_size这个参数,例如:
create table test (

) engine = innodb datafile_initial_size=100000;
如果设定的值比fil_ibd_file_initial_size还小,就依然传入fil_ibd_file_initial_size给fil_create_new_single_table_tablespace,否则传入datafile_initial_size进行初始化。
so, i add a new parameter for create table, named ‘datafile_initial_size'. for example:
create table test (

) engine = innodb datafile_initial_size=100000;
if datafile_initial_size value less than fil_ibd_file_initial_size, i will still pass fil_ibd_file_initial_size to fil_create_new_single_table_tablespace(), otherwise, i pass datafile_initial_size value to fil_create_new_single_table_tablespace() function for initialization.
因此,这个简单安全的patch就有了,可以看 http://bugs.mysql.com/bug.php?id=67792 关注官方的进展:
so, i wrote this simple patch, see http://bugs.mysql.com/bug.php?id=67792:

复制代码 代码如下:

index: storage/innobase/dict/dict0crea.c
===================================================================
--- storage/innobase/dict/dict0crea.c (revision 3063)
+++ storage/innobase/dict/dict0crea.c (working copy)
@@ -294,7 +294,8 @@
   error = fil_create_new_single_table_tablespace(
    space, path_or_name, is_path,
    flags == dict_tf_compact ? 0 : flags,
-   fil_ibd_file_initial_size);
+   table->datafile_initial_size < fil_ibd_file_initial_size ?
+        fil_ibd_file_initial_size : table->datafile_initial_size);
   table->space = (unsigned int) space;

   if (error != db_success) {
index: storage/innobase/handler/ha_innodb.cc
===================================================================
--- storage/innobase/handler/ha_innodb.cc (revision 3063)
+++ storage/innobase/handler/ha_innodb.cc (working copy)
@@ -7155,6 +7155,7 @@
    col_len);
  }

+  table->datafile_initial_size= form->datafile_initial_size;
  error = row_create_table_for_mysql(table, trx);

  if (error == db_duplicate_key) {
@@ -7760,6 +7761,7 @@

  row_mysql_lock_data_dictionary(trx);

+  form->datafile_initial_size= create_info->datafile_initial_size;
  error = create_table_def(trx, form, norm_name,
   create_info->options & ha_lex_create_tmp_table ? name2 : null,
   flags);
index: storage/innobase/include/dict0mem.h
===================================================================
--- storage/innobase/include/dict0mem.h (revision 3063)
+++ storage/innobase/include/dict0mem.h (working copy)
@@ -678,6 +678,7 @@
 /** value of dict_table_struct::magic_n */
 # define dict_table_magic_n 76333786
 #endif /* univ_debug */
+  uint datafile_initial_size; /* the initial size of the datafile */
 };

 #ifndef univ_noninl
index: support-files/mysql.5.5.18.spec
===================================================================
--- support-files/mysql.5.5.18.spec (revision 3063)
+++ support-files/mysql.5.5.18.spec (working copy)
@@ -244,7 +244,7 @@
 version:        5.5.18
 release:        %{release}%{?distro_releasetag:.%{distro_releasetag}}
 distribution:   %{distro_description}
-license:        copyright (c) 2000, 2011, %{mysql_vendor}. all rights reserved. under %{license_type} license as shown in the description field.
+license:        copyright (c) 2000, 2012, %{mysql_vendor}. all rights reserved. under %{license_type} license as shown in the description field.
 source:         http://www.mysql.com/downloads/mysql-5.5/%{src_dir}.tar.gz
 url:            http://www.mysql.com/
 packager:       mysql release engineering <mysql-build@oss.oracle.com>
index: sql/table.h
===================================================================
--- sql/table.h (revision 3063)
+++ sql/table.h (working copy)
@@ -596,6 +596,7 @@
   */
   key_map keys_in_use;
   key_map keys_for_keyread;
+  uint datafile_initial_size; /* the initial size of the datafile */
   ha_rows min_rows, max_rows;  /* create information */
   ulong   avg_row_length;  /* create information */
   ulong   version, mysql_version;
@@ -1094,6 +1095,8 @@
 #endif
   mdl_ticket *mdl_ticket;

+  uint datafile_initial_size;
+
   void init(thd *thd, table_list *tl);
   bool fill_item_list(list<item> *item_list) const;
   void reset_item_list(list<item> *item_list) const;
index: sql/sql_yacc.yy
===================================================================
--- sql/sql_yacc.yy (revision 3063)
+++ sql/sql_yacc.yy (working copy)
@@ -906,6 +906,7 @@
 %token  database
 %token  databases
 %token  datafile_sym
+%token  datafile_initial_size_sym
 %token  data_sym                      /* sql-2003-n */
 %token  datetime
 %token  date_add_interval             /* mysql-func */
@@ -5046,6 +5047,18 @@
             lex->create_info.db_type= $3;
             lex->create_info.used_fields|= ha_create_used_engine;
           }
+        | datafile_initial_size_sym opt_equal ulonglong_num
+          {
+            if ($3 > uint_max32)
+            {
+              lex->create_info.datafile_initial_size= uint_max32;
+            }
+            else
+            {
+              lex->create_info.datafile_initial_size= $3;
+            }
+            lex->create_info.used_fields|= ha_create_used_datafile_initial_size;
+          }
         | max_rows opt_equal ulonglong_num
           {
             lex->create_info.max_rows= $3;
@@ -12585,6 +12598,7 @@
         | cursor_name_sym          {}
         | data_sym                 {}
         | datafile_sym             {}
+        | datafile_initial_size_sym{}
         | datetime                 {}
         | date_sym                 {}
         | day_sym                  {}
index: sql/handler.h
===================================================================
--- sql/handler.h (revision 3063)
+++ sql/handler.h (working copy)
@@ -387,6 +387,8 @@
 #define ha_create_used_transactional    (1l << 20)
 /** unused. reserved for future versions. */
 #define ha_create_used_page_checksum    (1l << 21)
+/** used for innodb initial table size. */
+#define ha_create_used_datafile_initial_size (1l << 22)

 typedef ulonglong my_xid; // this line is the same as in log_event.h
 #define mysql_xid_prefix "mysqlxid"
@@ -1053,6 +1055,7 @@
   lex_string comment;
   const char *data_file_name, *index_file_name;
   const char *alias;
+  uint datafile_initial_size; /* the initial size of the datafile */
   ulonglong max_rows,min_rows;
   ulonglong auto_increment_value;
   ulong table_options;
index: sql/lex.h
===================================================================
--- sql/lex.h (revision 3063)
+++ sql/lex.h (working copy)
@@ -153,6 +153,7 @@
   { "database",  sym(database)},
   { "databases", sym(databases)},
   { "datafile",  sym(datafile_sym)},
+  { "datafile_initial_size",   sym(datafile_initial_size_sym)},
   { "date",  sym(date_sym)},
   { "datetime",  sym(datetime)},
   { "day",  sym(day_sym)},