]> git.pld-linux.org Git - packages/mysql.git/commitdiff
- percona patches updated by Eero Hänninen; rel 2
authorElan Ruusamäe <glen@pld-linux.org>
Thu, 16 Jul 2009 13:01:56 +0000 (13:01 +0000)
committercvs2git <feedback@pld-linux.org>
Sun, 24 Jun 2012 12:13:13 +0000 (12:13 +0000)
Changed files:
    mysql-innodb_dict_size_limit.patch -> 1.1
    mysql-innodb_extra_rseg.patch -> 1.1
    mysql-innodb_thread_concurrency_timer_based.patch -> 1.1
    mysql-mysql-test.patch -> 1.1
    mysql-profiling_slow.patch -> 1.1

mysql-innodb_dict_size_limit.patch [new file with mode: 0644]
mysql-innodb_extra_rseg.patch [new file with mode: 0644]
mysql-innodb_thread_concurrency_timer_based.patch [new file with mode: 0644]
mysql-mysql-test.patch [new file with mode: 0644]
mysql-profiling_slow.patch [new file with mode: 0644]

diff --git a/mysql-innodb_dict_size_limit.patch b/mysql-innodb_dict_size_limit.patch
new file mode 100644 (file)
index 0000000..8ef4e36
--- /dev/null
@@ -0,0 +1,477 @@
+diff -ru mysql-5.0.75_base/innobase/dict/dict0boot.c mysql-5.0.75/innobase/dict/dict0boot.c
+--- mysql-5.0.75_base/innobase/dict/dict0boot.c        2008-12-19 02:19:35.000000000 +0900
++++ mysql-5.0.75/innobase/dict/dict0boot.c     2009-01-23 19:28:25.000000000 +0900
+@@ -247,6 +247,7 @@
+       system tables */
+       /*-------------------------*/
+       table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE);
++      table->n_mysql_handles_opened = 1; /* for pin */
+       dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
+       dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
+@@ -283,6 +284,7 @@
+       ut_a(success);
+       /*-------------------------*/
+       table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE);
++      table->n_mysql_handles_opened = 1; /* for pin */
+       dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0);
+       dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
+@@ -309,6 +311,7 @@
+       ut_a(success);
+       /*-------------------------*/
+       table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE);
++      table->n_mysql_handles_opened = 1; /* for pin */
+       dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0);
+       dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
+@@ -345,6 +348,7 @@
+       ut_a(success);
+       /*-------------------------*/
+       table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE);
++      table->n_mysql_handles_opened = 1; /* for pin */
+       dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0);
+       dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
+diff -ru mysql-5.0.75_base/innobase/dict/dict0crea.c mysql-5.0.75/innobase/dict/dict0crea.c
+--- mysql-5.0.75_base/innobase/dict/dict0crea.c        2008-12-19 02:19:35.000000000 +0900
++++ mysql-5.0.75/innobase/dict/dict0crea.c     2009-01-23 19:41:38.000000000 +0900
+@@ -1178,6 +1178,9 @@
+               /* Foreign constraint system tables have already been
+               created, and they are ok */
++              table1->n_mysql_handles_opened = 1; /* for pin */
++              table2->n_mysql_handles_opened = 1; /* for pin */
++
+               mutex_exit(&(dict_sys->mutex));
+               return(DB_SUCCESS);
+@@ -1266,6 +1269,11 @@
+       
+       trx->op_info = "";
++      table1 = dict_table_get_low("SYS_FOREIGN");
++      table2 = dict_table_get_low("SYS_FOREIGN_COLS");
++      table1->n_mysql_handles_opened = 1; /* for pin */
++      table2->n_mysql_handles_opened = 1; /* for pin */
++
+       row_mysql_unlock_data_dictionary(trx);
+       trx_free_for_mysql(trx);
+diff -ru mysql-5.0.75_base/innobase/dict/dict0dict.c mysql-5.0.75/innobase/dict/dict0dict.c
+--- mysql-5.0.75_base/innobase/dict/dict0dict.c        2008-12-19 02:19:35.000000000 +0900
++++ mysql-5.0.75/innobase/dict/dict0dict.c     2009-01-26 16:03:29.000000000 +0900
+@@ -638,6 +638,8 @@
+       mutex_enter(&(dict_sys->mutex));
+       table = dict_table_get_on_id_low(table_id, trx);
++
++      dict_table_LRU_trim(table);
+       
+       mutex_exit(&(dict_sys->mutex));
+@@ -752,6 +754,8 @@
+       
+       table = dict_table_get_low(table_name);
++      dict_table_LRU_trim(table);
++
+       mutex_exit(&(dict_sys->mutex));
+       if (table != NULL) {
+@@ -787,6 +791,8 @@
+               table->n_mysql_handles_opened++;
+       }
++      dict_table_LRU_trim(table);
++
+       mutex_exit(&(dict_sys->mutex));
+       if (table != NULL) {
+@@ -1267,20 +1273,64 @@
+ too much space. Currently not used! */
+ void
+-dict_table_LRU_trim(void)
+-/*=====================*/
++dict_table_LRU_trim(
++/*================*/
++      dict_table_t*   self)
+ {
+       dict_table_t*   table;
+       dict_table_t*   prev_table;
++      dict_foreign_t* foreign;
++      ulint           n_removed;
++      ulint           n_have_parent;
++      ulint           cached_foreign_tables;
+-      ut_error;
++      //ut_error;
+ #ifdef UNIV_SYNC_DEBUG
+       ut_ad(mutex_own(&(dict_sys->mutex)));
+ #endif /* UNIV_SYNC_DEBUG */
++retry:
++      n_removed = n_have_parent = 0;
+       table = UT_LIST_GET_LAST(dict_sys->table_LRU);
++      while ( srv_dict_size_limit && table
++              && ((dict_sys->table_hash->n_cells
++                   + dict_sys->table_id_hash->n_cells
++                   + dict_sys->col_hash->n_cells) * sizeof(hash_cell_t)
++                  + dict_sys->size) > srv_dict_size_limit ) {
++              prev_table = UT_LIST_GET_PREV(table_LRU, table);
++
++              if (table == self || table->n_mysql_handles_opened)
++                      goto next_loop;
++
++              cached_foreign_tables = 0;
++              foreign = UT_LIST_GET_FIRST(table->foreign_list);
++              while (foreign != NULL) {
++                      if (foreign->referenced_table)
++                              cached_foreign_tables++;
++                      foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
++              }
++
++              /* TODO: use table->mem_fix also, if it becomes exact. */
++
++              if (cached_foreign_tables == 0) {
++                      dict_table_remove_from_cache(table);
++                      n_removed++;
++              } else {
++                      n_have_parent++;
++              }
++next_loop:
++              table = prev_table;
++      }
++
++      if ( srv_dict_size_limit && n_have_parent && n_removed
++              && ((dict_sys->table_hash->n_cells
++                   + dict_sys->table_id_hash->n_cells
++                   + dict_sys->col_hash->n_cells) * sizeof(hash_cell_t)
++                  + dict_sys->size) > srv_dict_size_limit )
++              goto retry;
++/*
+       while (table && (dict_sys->size >
+                        buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) {
+@@ -1292,6 +1341,7 @@
+               table = prev_table;
+       }
++*/
+ }
+ /**************************************************************************
+diff -ru mysql-5.0.75_base/innobase/ibuf/ibuf0ibuf.c mysql-5.0.75/innobase/ibuf/ibuf0ibuf.c
+--- mysql-5.0.75_base/innobase/ibuf/ibuf0ibuf.c        2009-01-23 11:44:18.000000000 +0900
++++ mysql-5.0.75/innobase/ibuf/ibuf0ibuf.c     2009-01-23 19:22:54.000000000 +0900
+@@ -535,6 +535,7 @@
+       sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
+       /* use old-style record format for the insert buffer */
+       table = dict_mem_table_create(buf, space, 2, FALSE);
++      table->n_mysql_handles_opened = 1; /* for pin */
+       dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0);
+       dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0);
+diff -ru mysql-5.0.75_base/innobase/include/dict0dict.h mysql-5.0.75/innobase/include/dict0dict.h
+--- mysql-5.0.75_base/innobase/include/dict0dict.h     2008-12-19 02:19:35.000000000 +0900
++++ mysql-5.0.75/innobase/include/dict0dict.h  2009-01-23 21:46:22.000000000 +0900
+@@ -938,6 +938,11 @@
+       const char*     ptr,    /* in: scan from */
+       const char*     string);/* in: look for this */
++void
++dict_table_LRU_trim(
++/*================*/
++      dict_table_t*   self);
++
+ /* Buffers for storing detailed information about the latest foreign key
+ and unique key errors */
+ extern FILE*  dict_foreign_err_file;
+diff -ru mysql-5.0.75_base/innobase/include/dict0dict.ic mysql-5.0.75/innobase/include/dict0dict.ic
+--- mysql-5.0.75_base/innobase/include/dict0dict.ic    2008-12-19 02:19:35.000000000 +0900
++++ mysql-5.0.75/innobase/include/dict0dict.ic 2009-01-23 18:35:55.000000000 +0900
+@@ -533,6 +533,13 @@
+       HASH_SEARCH(name_hash, dict_sys->table_hash, table_fold, table,
+                               ut_strcmp(table->name, table_name) == 0);
++
++      /* make young in table_LRU */
++      if (table) {
++              UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
++              UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
++      }
++
+       return(table);
+ }
+@@ -592,6 +599,10 @@
+       if (table != NULL) {
+               table->mem_fix++;
++              /* make young in table_LRU */
++              UT_LIST_REMOVE(table_LRU, dict_sys->table_LRU, table);
++              UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table);
++
+               /* lock_push(trx, table, LOCK_DICT_MEM_FIX) */
+       }
+       
+diff -ru mysql-5.0.75_base/innobase/include/srv0srv.h mysql-5.0.75/innobase/include/srv0srv.h
+--- mysql-5.0.75_base/innobase/include/srv0srv.h       2009-01-23 11:44:19.000000000 +0900
++++ mysql-5.0.75/innobase/include/srv0srv.h    2009-01-27 10:47:26.000000000 +0900
+@@ -146,6 +146,8 @@
+ extern uint   srv_read_ahead;
+ extern ulint  srv_adaptive_checkpoint;
++extern ulint  srv_dict_size_limit;
++
+ extern volatile ibool srv_io_pattern;
+ extern ulong  srv_io_pattern_trace;
+ extern ulong  srv_io_pattern_trace_running;
+@@ -545,6 +547,7 @@
+         ulint innodb_data_writes;
+         ulint innodb_data_written;
+         ulint innodb_data_reads;
++        ulint innodb_dict_tables;
+         ulint innodb_buffer_pool_pages_total;
+         ulint innodb_buffer_pool_pages_data;
+         ulint innodb_buffer_pool_pages_dirty;
+diff -ru mysql-5.0.75_base/innobase/srv/srv0srv.c mysql-5.0.75/innobase/srv/srv0srv.c
+--- mysql-5.0.75_base/innobase/srv/srv0srv.c   2009-01-23 11:44:19.000000000 +0900
++++ mysql-5.0.75/innobase/srv/srv0srv.c        2009-01-27 10:52:19.000000000 +0900
+@@ -345,6 +345,8 @@
+ uint  srv_read_ahead = 3; /* 1: random  2: linear  3: Both */
+ ulint srv_adaptive_checkpoint = 0; /* 0:disable 1:enable */
++ulint srv_dict_size_limit = 0;
++
+ volatile ibool srv_io_pattern = FALSE;
+ ulint   srv_io_pattern_trace = 0;
+ ulint   srv_io_pattern_trace_running = 0;
+@@ -1936,6 +1938,7 @@
+         export_vars.innodb_data_reads= os_n_file_reads;
+         export_vars.innodb_data_writes= os_n_file_writes;
+         export_vars.innodb_data_written= srv_data_written;
++        export_vars.innodb_dict_tables= (dict_sys ? UT_LIST_GET_LEN(dict_sys->table_LRU) : 0);
+         export_vars.innodb_buffer_pool_read_requests= buf_pool->n_page_gets;
+         export_vars.innodb_buffer_pool_write_requests= srv_buf_pool_write_requests;
+         export_vars.innodb_buffer_pool_wait_free= srv_buf_pool_wait_free;
+diff -ru mysql-5.0.75_base/sql/ha_innodb.cc mysql-5.0.75/sql/ha_innodb.cc
+--- mysql-5.0.75_base/sql/ha_innodb.cc 2009-01-23 11:44:19.000000000 +0900
++++ mysql-5.0.75/sql/ha_innodb.cc      2009-01-27 10:54:08.000000000 +0900
+@@ -288,6 +288,8 @@
+   (char*) &export_vars.innodb_dblwr_pages_written,        SHOW_LONG},
+   {"dblwr_writes",
+   (char*) &export_vars.innodb_dblwr_writes,               SHOW_LONG},
++  {"dict_tables",
++  (char*) &export_vars.innodb_dict_tables,                SHOW_LONG},
+   {"log_waits",
+   (char*) &export_vars.innodb_log_waits,                  SHOW_LONG},
+   {"log_write_requests",
+diff -ru mysql-5.0.75_base/sql/ha_innodb.h mysql-5.0.75/sql/ha_innodb.h
+--- mysql-5.0.75_base/sql/ha_innodb.h  2009-01-23 11:44:19.000000000 +0900
++++ mysql-5.0.75/sql/ha_innodb.h       2009-01-26 15:49:37.000000000 +0900
+@@ -242,6 +242,7 @@
+ extern ulong srv_flush_neighbor_pages;
+ extern uint srv_read_ahead;
+ extern ulong srv_adaptive_checkpoint;
++extern ulong srv_dict_size_limit;
+ extern ulong srv_show_locks_held;
+ extern ulong srv_show_verbose_locks;
+ extern ulong srv_io_pattern_trace;
+diff -ru mysql-5.0.75_base/sql/mysqld.cc mysql-5.0.75/sql/mysqld.cc
+--- mysql-5.0.75_base/sql/mysqld.cc    2009-01-23 11:44:19.000000000 +0900
++++ mysql-5.0.75/sql/mysqld.cc 2009-01-26 15:29:45.000000000 +0900
+@@ -5053,6 +5053,7 @@
+   OPT_INNODB_ADAPTIVE_CHECKPOINT,
+   OPT_INNODB_READ_IO_THREADS,
+   OPT_INNODB_WRITE_IO_THREADS,
++  OPT_INNODB_DICT_SIZE_LIMIT,
+   OPT_INNODB_ADAPTIVE_HASH_INDEX,
+   OPT_RPL_MIRROR_BINLOG,
+   OPT_SYNC_MIRROR_BINLOG,
+@@ -5406,6 +5407,10 @@
+    "Number of background write I/O threads in InnoDB.",
+    (gptr*) &innobase_write_io_threads, (gptr*) &innobase_write_io_threads,
+    0, GET_LONG, REQUIRED_ARG, 1, 1, 64, 0, 0, 0},
++  {"innodb_dict_size_limit", OPT_INNODB_DICT_SIZE_LIMIT,
++   "Limit the allocated memory for dictionary cache. (0: unlimited)",
++   (gptr*) &srv_dict_size_limit, (gptr*) &srv_dict_size_limit, 0,
++   GET_ULONG, REQUIRED_ARG, 0, 0, ULONG_MAX, 0, 0 ,0},
+   {"innodb_io_pattern_trace", OPT_INNODB_IO_PATTERN_TRACE,
+    "Create/Drop the internal hash table for IO pattern tracing.",
+    (gptr*) &srv_io_pattern_trace, (gptr*) &srv_io_pattern_trace,
+diff -ru mysql-5.0.75_base/sql/set_var.cc mysql-5.0.75/sql/set_var.cc
+--- mysql-5.0.75_base/sql/set_var.cc   2009-01-23 11:44:19.000000000 +0900
++++ mysql-5.0.75/sql/set_var.cc        2009-01-26 15:46:45.000000000 +0900
+@@ -522,6 +522,8 @@
+                                       &innodb_read_ahead_typelib, fix_innodb_read_ahead);
+ sys_var_long_ptr      sys_innodb_adaptive_checkpoint("innodb_adaptive_checkpoint",
+                                                       &srv_adaptive_checkpoint);
++sys_var_long_ptr      sys_innodb_dict_size_limit("innodb_dict_size_limit",
++                                                   &srv_dict_size_limit);
+ sys_var_long_ptr  sys_innodb_show_locks_held(
+                                         "innodb_show_locks_held",
+                                         &srv_show_locks_held);
+@@ -905,6 +907,7 @@
+   &sys_innodb_flush_neighbor_pages,
+   &sys_innodb_read_ahead,
+   &sys_innodb_adaptive_checkpoint,
++  &sys_innodb_dict_size_limit,
+   &sys_innodb_show_locks_held,
+   &sys_innodb_show_verbose_locks,
+   &sys_innodb_io_pattern_trace,
+@@ -1056,6 +1059,7 @@
+   {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS},
+   {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG},
+   {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG},
++  {sys_innodb_dict_size_limit.name, (char*) &sys_innodb_dict_size_limit, SHOW_SYS},
+   {sys_innodb_io_pattern_trace.name, (char*) &sys_innodb_io_pattern_trace, SHOW_SYS},
+   {sys_innodb_io_pattern_trace_running.name, (char*) &sys_innodb_io_pattern_trace_running, SHOW_SYS},
+   {sys_innodb_io_pattern_size_limit.name, (char*) &sys_innodb_io_pattern_size_limit, SHOW_SYS},
+diff -ruN mysql-5.0.75_base/mysql-test/r/innodb_dict_size_limit.result mysql-5.0.75/mysql-test/r/innodb_dict_size_limit.result
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.0.75/mysql-test/r/innodb_dict_size_limit.result    2009-01-27 11:43:46.000000000 +0900
+@@ -0,0 +1,60 @@
++DROP TABLE IF EXISTS `test_5`;
++DROP TABLE IF EXISTS `test_4`;
++DROP TABLE IF EXISTS `test_3`;
++DROP TABLE IF EXISTS `test_2`;
++DROP TABLE IF EXISTS `test_1`;
++SET storage_engine=InnoDB;
++SET GLOBAL innodb_dict_size_limit=1;
++FLUSH TABLES;
++CREATE TABLE `test_1` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_2` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_3` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_4` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_5` (`a` int, `b` int, PRIMARY KEY  (`a`));
++ALTER TABLE `test_5` ADD CONSTRAINT FOREIGN KEY(`b`) REFERENCES `test_4`(`a`);
++ALTER TABLE `test_4` ADD CONSTRAINT FOREIGN KEY(`b`) REFERENCES `test_3`(`a`);
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    9
++FLUSH TABLES;
++SELECT * FROM `test_1`;
++a     b
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    8
++SELECT * FROM `test_3`;
++a     b
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    11
++FLUSH TABLES;
++SELECT * FROM `test_2`;
++a     b
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    8
++SELECT * FROM `test_1`;
++a     b
++FLUSH TABLES;
++SELECT * FROM `test_4`;
++a     b
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    9
++SELECT * FROM `test_3`;
++a     b
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    10
++SET GLOBAL innodb_dict_size_limit=0;
++FLUSH TABLES;
++SELECT * FROM `test_2`;
++a     b
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++Variable_name Value
++Innodb_dict_tables    11
++DROP TABLE `test_5`;
++DROP TABLE `test_4`;
++DROP TABLE `test_3`;
++DROP TABLE `test_2`;
++DROP TABLE `test_1`;
+diff -ruN mysql-5.0.75_base/mysql-test/t/innodb_dict_size_limit.test mysql-5.0.75/mysql-test/t/innodb_dict_size_limit.test
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.0.75/mysql-test/t/innodb_dict_size_limit.test      2009-01-27 11:43:36.000000000 +0900
+@@ -0,0 +1,63 @@
++#
++# Test for new variable innodb_dict_size_limit;
++#
++-- source include/have_innodb.inc
++
++--disable_warnings
++DROP TABLE IF EXISTS `test_5`;
++DROP TABLE IF EXISTS `test_4`;
++DROP TABLE IF EXISTS `test_3`;
++DROP TABLE IF EXISTS `test_2`;
++DROP TABLE IF EXISTS `test_1`;
++--enable_warnings
++
++SET storage_engine=InnoDB;
++SET GLOBAL innodb_dict_size_limit=1;
++
++FLUSH TABLES;
++
++CREATE TABLE `test_1` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_2` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_3` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_4` (`a` int, `b` int, PRIMARY KEY  (`a`));
++CREATE TABLE `test_5` (`a` int, `b` int, PRIMARY KEY  (`a`));
++
++ALTER TABLE `test_5` ADD CONSTRAINT FOREIGN KEY(`b`) REFERENCES `test_4`(`a`);
++ALTER TABLE `test_4` ADD CONSTRAINT FOREIGN KEY(`b`) REFERENCES `test_3`(`a`);
++
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++FLUSH TABLES;
++SELECT * FROM `test_1`;
++
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++SELECT * FROM `test_3`;
++
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++FLUSH TABLES;
++SELECT * FROM `test_2`;
++
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++SELECT * FROM `test_1`;
++FLUSH TABLES;
++SELECT * FROM `test_4`;
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++SELECT * FROM `test_3`;
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++SET GLOBAL innodb_dict_size_limit=0;
++FLUSH TABLES;
++SELECT * FROM `test_2`;
++
++SHOW GLOBAL STATUS LIKE 'Innodb_dict_tables';
++
++DROP TABLE `test_5`;
++DROP TABLE `test_4`;
++DROP TABLE `test_3`;
++DROP TABLE `test_2`;
++DROP TABLE `test_1`;
++
+diff -ruN mysql-5.0.75_base/patch_info/innodb_dict_size_limit.info mysql-5.0.75/patch_info/innodb_dict_size_limit.info
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ mysql-5.0.75/patch_info/innodb_dict_size_limit.info        2009-01-26 15:46:45.000000000 +0900
+@@ -0,0 +1,9 @@
++File=innodb_dict_size_limit.patch
++Name=Limit dictionary cache size
++Version=1.0
++Author=Percona
++License=GPL
++Comment=Variable innodb_dict_size_limit in bytes
++ChangeLog=
++2009-01-26
++YK: Initial release
diff --git a/mysql-innodb_extra_rseg.patch b/mysql-innodb_extra_rseg.patch
new file mode 100644 (file)
index 0000000..1c8f429
--- /dev/null
@@ -0,0 +1,243 @@
+diff -ruN a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
+--- a/innobase/include/srv0srv.h       2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/include/srv0srv.h       2009-05-06 13:37:45.000000000 +0900
+@@ -147,6 +147,8 @@
+ extern uint   srv_read_ahead;
+ extern ulint  srv_adaptive_checkpoint;
++extern ulint  srv_extra_rsegments;
++
+ extern ulint  srv_dict_size_limit;
+ extern volatile ibool srv_io_pattern;
+diff -ruN a/innobase/include/trx0sys.h b/innobase/include/trx0sys.h
+--- a/innobase/include/trx0sys.h       2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/include/trx0sys.h       2009-05-06 14:52:00.000000000 +0900
+@@ -105,6 +105,13 @@
+ void
+ trx_sys_create(void);
+ /*================*/
++/*********************************************************************
++Create extra rollback segments when create_new_db */
++
++void
++trx_sys_create_extra_rseg(
++/*======================*/
++      ulint   num);   /* in: number of extra user rollback segments */
+ /********************************************************************
+ Looks for a free slot for a rollback segment in the trx system file copy. */
+diff -ruN a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
+--- a/innobase/srv/srv0srv.c   2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/srv/srv0srv.c   2009-05-06 13:38:23.000000000 +0900
+@@ -347,6 +347,8 @@
+ uint  srv_read_ahead = 3; /* 1: random  2: linear  3: Both */
+ ulint srv_adaptive_checkpoint = 0; /* 0:disable 1:enable */
++ulint srv_extra_rsegments = 0; /* extra rseg for users */
++
+ ulint srv_dict_size_limit = 0;
+ volatile ibool srv_io_pattern = FALSE;
+diff -ruN a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
+--- a/innobase/srv/srv0start.c 2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/srv/srv0start.c 2009-05-06 14:54:43.000000000 +0900
+@@ -1418,6 +1418,8 @@
+               dict_create();
+                 srv_startup_is_before_trx_rollback_phase = FALSE;
++              if (srv_extra_rsegments)
++                      trx_sys_create_extra_rseg(srv_extra_rsegments);
+ #ifdef UNIV_LOG_ARCHIVE
+       } else if (srv_archive_recovery) {
+               fprintf(stderr,
+diff -ruN a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
+--- a/innobase/trx/trx0sys.c   2009-05-06 15:35:46.000000000 +0900
++++ b/innobase/trx/trx0sys.c   2009-05-06 14:54:02.000000000 +0900
+@@ -944,3 +944,28 @@
+       trx_sys_init_at_db_start();
+ }
++
++/*********************************************************************
++Create extra rollback segments when create_new_db */
++
++void
++trx_sys_create_extra_rseg(
++/*======================*/
++      ulint   num)    /* in: number of extra user rollback segments */
++{
++      mtr_t   mtr;
++      ulint   slot_no;
++      ulint   i;
++
++      /* Craete extra rollback segments */
++      mtr_start(&mtr);
++      for (i = 1; i < num + 1; i++) {
++              if(!trx_rseg_create(TRX_SYS_SPACE, ULINT_MAX, &slot_no, &mtr)) {
++                      fprintf(stderr,
++"InnoDB: Warning: Failed to create extra rollback segments.\n");
++                      break;
++              }
++              ut_a(slot_no == i);
++      }
++      mtr_commit(&mtr);
++}
+diff -ruN a/patch_info/innodb_extra_rseg.info b/patch_info/innodb_extra_rseg.info
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ b/patch_info/innodb_extra_rseg.info        2009-05-06 14:49:48.000000000 +0900
+@@ -0,0 +1,6 @@
++File=innodb_extra_rseg.patch
++Name=allow to create extra rollback segments
++Version=1.0
++Author=Percona <info@percona.com>
++License=GPL
++Comment
+diff -ruN a/sql/ha_innodb.cc b/sql/ha_innodb.cc
+--- a/sql/ha_innodb.cc 2009-05-06 15:35:46.000000000 +0900
++++ b/sql/ha_innodb.cc 2009-05-06 15:27:49.000000000 +0900
+@@ -152,6 +152,7 @@
+      innobase_open_files;
+ long innobase_read_io_threads, innobase_write_io_threads;
++long innobase_extra_rsegments;
+ longlong innobase_buffer_pool_size, innobase_log_file_size;
+ /* The default values for the following char* start-up parameters
+@@ -1507,6 +1508,8 @@
+       srv_n_read_io_threads = (ulint) innobase_read_io_threads;
+       srv_n_write_io_threads = (ulint) innobase_write_io_threads;
++      srv_extra_rsegments = (ulint) innobase_extra_rsegments;
++
+       srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
+       srv_force_recovery = (ulint) innobase_force_recovery;
+diff -ruN a/sql/ha_innodb.h b/sql/ha_innodb.h
+--- a/sql/ha_innodb.h  2009-05-06 15:35:46.000000000 +0900
++++ b/sql/ha_innodb.h  2009-05-06 13:51:35.000000000 +0900
+@@ -205,6 +205,7 @@
+ extern long innobase_buffer_pool_awe_mem_mb;
+ extern long innobase_file_io_threads, innobase_lock_wait_timeout;
+ extern long innobase_read_io_threads, innobase_write_io_threads;
++extern long innobase_extra_rsegments;
+ extern long innobase_force_recovery;
+ extern long innobase_open_files;
+ extern char *innobase_data_home_dir, *innobase_data_file_path;
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc    2009-05-06 15:35:46.000000000 +0900
++++ b/sql/mysqld.cc    2009-05-06 14:12:05.000000000 +0900
+@@ -5096,6 +5096,7 @@
+   OPT_INNODB_ADAPTIVE_CHECKPOINT,
+   OPT_INNODB_READ_IO_THREADS,
+   OPT_INNODB_WRITE_IO_THREADS,
++  OPT_INNODB_EXTRA_RSEGMENTS,
+   OPT_INNODB_DICT_SIZE_LIMIT,
+   OPT_INNODB_ADAPTIVE_HASH_INDEX,
+   OPT_RPL_MIRROR_BINLOG,
+@@ -5454,6 +5455,10 @@
+    "Number of background write I/O threads in InnoDB.",
+    (gptr*) &innobase_write_io_threads, (gptr*) &innobase_write_io_threads,
+    0, GET_LONG, REQUIRED_ARG, 1, 1, 64, 0, 0, 0},
++  {"innodb_extra_rsegments", OPT_INNODB_EXTRA_RSEGMENTS,
++   "Number of extra user rollback segments when create new database.",
++   (gptr*) &innobase_extra_rsegments, (gptr*) &innobase_extra_rsegments,
++   0, GET_LONG, REQUIRED_ARG, 0, 0, 127, 0, 0, 0},
+   {"innodb_dict_size_limit", OPT_INNODB_DICT_SIZE_LIMIT,
+    "Limit the allocated memory for dictionary cache. (0: unlimited)",
+    (gptr*) &srv_dict_size_limit, (gptr*) &srv_dict_size_limit, 0,
+diff -ruN a/sql/set_var.cc b/sql/set_var.cc
+--- a/sql/set_var.cc   2009-05-06 15:35:46.000000000 +0900
++++ b/sql/set_var.cc   2009-05-06 14:13:24.000000000 +0900
+@@ -1063,6 +1063,7 @@
+   {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS},
+   {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG},
+   {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG},
++  {"innodb_extra_rsegments", (char*) &innobase_extra_rsegments, SHOW_LONG},
+   {sys_innodb_dict_size_limit.name, (char*) &sys_innodb_dict_size_limit, SHOW_SYS},
+   {sys_innodb_io_pattern_trace.name, (char*) &sys_innodb_io_pattern_trace, SHOW_SYS},
+   {sys_innodb_io_pattern_trace_running.name, (char*) &sys_innodb_io_pattern_trace_running, SHOW_SYS},
+diff -ruN a/sql/sql_show.cc b/sql/sql_show.cc
+--- a/sql/sql_show.cc  2009-05-06 15:35:46.000000000 +0900
++++ b/sql/sql_show.cc  2009-05-06 15:29:47.000000000 +0900
+@@ -39,6 +39,8 @@
+ #include "srv0srv.h"
+ #include "buf0buf.h"
+ #include "dict0dict.h"
++#include "trx0rseg.h" /* for trx_rseg_struct */
++#include "trx0sys.h" /* for trx_sys */
+ }
+ /* We need to undef it in InnoDB */
+ #undef byte
+@@ -4160,6 +4162,45 @@
+   DBUG_RETURN(returnable);
+ }
++int
++innodb_rseg_fill(
++/*=================*/
++      THD*            thd,    /* in: thread */
++      TABLE_LIST*     tables, /* in/out: tables to fill */
++      COND*           cond)   /* in: condition (ignored) */
++{
++      TABLE*  table   = (TABLE *) tables->table;
++      int     status  = 0;
++      trx_rseg_t*     rseg;
++
++      DBUG_ENTER("innodb_rseg_fill");
++
++      /* deny access to non-superusers */
++      if (check_global_access(thd, PROCESS_ACL)) {
++
++              DBUG_RETURN(0);
++      }
++
++      rseg = UT_LIST_GET_FIRST(trx_sys->rseg_list);
++
++      while (rseg) {
++              table->field[0]->store(rseg->id);
++              table->field[1]->store(rseg->space);
++              table->field[2]->store(rseg->page_no);
++              table->field[3]->store(rseg->max_size);
++              table->field[4]->store(rseg->curr_size);
++
++              if (schema_table_store_record(thd, table)) {
++                      status = 1;
++                      break;
++              }
++
++              rseg = UT_LIST_GET_NEXT(rseg_list, rseg);
++      }
++
++      DBUG_RETURN(status);
++}
++
+ /*
+   Find schema_tables elment by name
+@@ -4978,6 +5019,16 @@
+   {"N_WRITE", 11, MYSQL_TYPE_LONG, 0, 0, "write ios"},
+   {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+ };
++
++ST_FIELD_INFO innodb_rseg_fields_info[]=
++{
++  {"RSEG_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, ""},
++  {"SPACE_ID", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, ""},
++  {"PAGE_NO", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, ""},
++  {"MAX_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, ""},
++  {"CURR_SIZE", MY_INT64_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONG, 0, 0, ""},
++  {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
++};
+ #endif
+ ST_FIELD_INFO variables_fields_info[]=
+@@ -5157,6 +5208,8 @@
+ #ifdef HAVE_INNOBASE_DB
+   {"INNODB_IO_PATTERN", innodb_io_pattern_field_info, create_schema_table,
+     innodb_io_pattern_fill_table, 0, 0, -1, -1, 0},
++  {"INNODB_RSEG", innodb_rseg_fields_info, create_schema_table,
++    innodb_rseg_fill, 0, 0, -1, -1, 0},
+ #endif
+   {0, 0, 0, 0, 0, 0, 0, 0, 0}
+ };
diff --git a/mysql-innodb_thread_concurrency_timer_based.patch b/mysql-innodb_thread_concurrency_timer_based.patch
new file mode 100644 (file)
index 0000000..5e26818
--- /dev/null
@@ -0,0 +1,389 @@
+diff -ruN a/innobase/configure b/innobase/configure
+--- a/innobase/configure       2009-01-30 06:56:31.000000000 +0900
++++ b/innobase/configure       2009-05-06 15:40:47.000000000 +0900
+@@ -21306,6 +21306,88 @@
+ fi
+ done
++
++# as http://lists.mysql.com/commits/40686 does
++{ echo "$as_me:$LINENO: checking whether the compiler provides atomic builtins" >&5
++echo $ECHO_N "checking whether the compiler provides atomic builtins... $ECHO_C" >&6; }
++if test "${mysql_cv_atomic_builtins+set}" = set; then
++  echo $ECHO_N "(cached) $ECHO_C" >&6
++else
++  if test "$cross_compiling" = yes; then
++  { { echo "$as_me:$LINENO: error: cannot run test program while cross compiling
++See \`config.log' for more details." >&5
++echo "$as_me: error: cannot run test program while cross compiling
++See \`config.log' for more details." >&2;}
++   { (exit 1); exit 1; }; }
++else
++  cat >conftest.$ac_ext <<_ACEOF
++/* confdefs.h.  */
++_ACEOF
++cat confdefs.h >>conftest.$ac_ext
++cat >>conftest.$ac_ext <<_ACEOF
++/* end confdefs.h.  */
++
++  int main()
++  {
++    int foo= -10; int bar= 10;
++    __sync_fetch_and_add(&foo, bar);
++    if (foo)
++      return -1;
++    bar= __sync_lock_test_and_set(&foo, bar);
++    if (bar || foo != 10)
++      return -1;
++    bar= __sync_val_compare_and_swap(&bar, foo, 15);
++    if (bar)
++      return -1;
++    return 0;
++  }
++
++_ACEOF
++rm -f conftest$ac_exeext
++if { (ac_try="$ac_link"
++case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++  (eval "$ac_link") 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); } && { ac_try='./conftest$ac_exeext'
++  { (case "(($ac_try" in
++  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
++  *) ac_try_echo=$ac_try;;
++esac
++eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
++  (eval "$ac_try") 2>&5
++  ac_status=$?
++  echo "$as_me:$LINENO: \$? = $ac_status" >&5
++  (exit $ac_status); }; }; then
++  mysql_cv_atomic_builtins=yes
++else
++  echo "$as_me: program exited with status $ac_status" >&5
++echo "$as_me: failed program was:" >&5
++sed 's/^/| /' conftest.$ac_ext >&5
++
++( exit $ac_status )
++mysql_cv_atomic_builtins=no
++fi
++rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext
++fi
++
++
++fi
++{ echo "$as_me:$LINENO: result: $mysql_cv_atomic_builtins" >&5
++echo "${ECHO_T}$mysql_cv_atomic_builtins" >&6; }
++
++if test "x$mysql_cv_atomic_builtins" = xyes; then
++
++cat >>confdefs.h <<\_ACEOF
++#define HAVE_ATOMIC_BUILTINS 1
++_ACEOF
++
++fi
++
+ #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
+ # Some versions of Unix only take 2 arguments.
+ #AC_C_INLINE  Already checked in MySQL
+diff -ruN a/innobase/configure.in b/innobase/configure.in
+--- a/innobase/configure.in    2009-01-30 06:42:15.000000000 +0900
++++ b/innobase/configure.in    2009-05-06 15:40:47.000000000 +0900
+@@ -42,6 +42,31 @@
+ AC_CHECK_FUNCS(sched_yield)
+ AC_CHECK_FUNCS(fdatasync)
+ AC_CHECK_FUNCS(localtime_r)
++
++# as http://lists.mysql.com/commits/40686 does
++AC_CACHE_CHECK([whether the compiler provides atomic builtins],
++               [mysql_cv_atomic_builtins], [AC_TRY_RUN([
++  int main()
++  {
++    int foo= -10; int bar= 10;
++    __sync_fetch_and_add(&foo, bar);
++    if (foo)
++      return -1;
++    bar= __sync_lock_test_and_set(&foo, bar);
++    if (bar || foo != 10)
++      return -1;
++    bar= __sync_val_compare_and_swap(&bar, foo, 15);
++    if (bar)
++      return -1;
++    return 0;
++  }
++], [mysql_cv_atomic_builtins=yes], [mysql_cv_atomic_builtins=no])])
++
++if test "x$mysql_cv_atomic_builtins" = xyes; then
++  AC_DEFINE(HAVE_ATOMIC_BUILTINS, 1,
++            [Define to 1 if compiler provides atomic builtins.])
++fi
++
+ #AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
+ # Some versions of Unix only take 2 arguments.
+ #AC_C_INLINE  Already checked in MySQL
+diff -ruN a/innobase/ib_config.h b/innobase/ib_config.h
+--- a/innobase/ib_config.h     2009-01-30 07:05:03.000000000 +0900
++++ b/innobase/ib_config.h     2009-05-06 15:40:47.000000000 +0900
+@@ -7,6 +7,9 @@
+ /* Define to 1 if you have the <aio.h> header file. */
+ #define HAVE_AIO_H 1
++/* Define to 1 if compiler provides atomic builtins. */
++#define HAVE_ATOMIC_BUILTINS 1
++
+ /* Define to 1 if you have the <dlfcn.h> header file. */
+ #define HAVE_DLFCN_H 1
+diff -ruN a/innobase/ib_config.h.in b/innobase/ib_config.h.in
+--- a/innobase/ib_config.h.in  2009-01-30 06:56:11.000000000 +0900
++++ b/innobase/ib_config.h.in  2009-05-06 15:40:47.000000000 +0900
+@@ -6,6 +6,9 @@
+ /* Define to 1 if you have the <aio.h> header file. */
+ #undef HAVE_AIO_H
++/* Define to 1 if compiler provides atomic builtins. */
++#undef HAVE_ATOMIC_BUILTINS
++
+ /* Define to 1 if you have the <dlfcn.h> header file. */
+ #undef HAVE_DLFCN_H
+diff -ruN a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
+--- a/innobase/include/srv0srv.h       2009-05-06 15:38:01.000000000 +0900
++++ b/innobase/include/srv0srv.h       2009-05-06 16:04:36.000000000 +0900
+@@ -90,6 +90,8 @@
+ extern ulint  srv_mem_pool_size;
+ extern ulint  srv_lock_table_size;
++extern ibool  srv_thread_concurrency_timer_based;
++
+ extern ulint  srv_n_file_io_threads;
+ extern ulint  srv_n_read_io_threads;
+ extern ulint  srv_n_write_io_threads;
+diff -ruN a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
+--- a/innobase/srv/srv0srv.c   2009-05-06 15:38:01.000000000 +0900
++++ b/innobase/srv/srv0srv.c   2009-05-06 17:12:54.000000000 +0900
+@@ -267,6 +267,7 @@
+ computer. Bigger computers need bigger values. Value 0 will disable the
+ concurrency check. */
++ibool srv_thread_concurrency_timer_based = TRUE;
+ ulong srv_thread_concurrency  = 0;
+ ulong   srv_commit_concurrency  = 0;
+@@ -1020,6 +1021,74 @@
+ Puts an OS thread to wait if there are too many concurrent threads
+ (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */
++#ifdef HAVE_ATOMIC_BUILTINS
++static void
++enter_innodb_with_tickets(trx_t* trx)
++{
++      trx->declared_to_be_inside_innodb = TRUE;
++      trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER;
++      return;
++}
++
++static void
++srv_conc_enter_innodb_timer_based(trx_t* trx)
++{
++      lint    conc_n_threads;
++      ibool   has_yielded = FALSE;
++      ulint   has_slept = 0;
++
++      if (trx->declared_to_be_inside_innodb) {
++              ut_print_timestamp(stderr);
++              fputs(
++"  InnoDB: Error: trying to declare trx to enter InnoDB, but\n"
++"InnoDB: it already is declared.\n", stderr);
++              trx_print(stderr, trx, 0);
++              putc('\n', stderr);
++      }
++retry:
++      if (srv_conc_n_threads < (lint) srv_thread_concurrency) {
++              conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1);
++              if (conc_n_threads <= (lint) srv_thread_concurrency) {
++                      enter_innodb_with_tickets(trx);
++                      return;
++              }
++              __sync_add_and_fetch(&srv_conc_n_threads, -1);
++      }
++      if (!has_yielded)
++      {
++              has_yielded = TRUE;
++              os_thread_yield();
++              goto retry;
++      }
++      if (trx->has_search_latch
++          || NULL != UT_LIST_GET_FIRST(trx->trx_locks)) {
++
++              conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1);
++              enter_innodb_with_tickets(trx);
++              return;
++      }
++      if (has_slept < 2)
++      {
++              trx->op_info = "sleeping before entering InnoDB";
++              os_thread_sleep(10000);
++              trx->op_info = "";
++              has_slept++;
++      }
++      conc_n_threads = __sync_add_and_fetch(&srv_conc_n_threads, 1);
++      enter_innodb_with_tickets(trx);
++      return;
++}
++
++static void
++srv_conc_exit_innodb_timer_based(trx_t* trx)
++{
++      __sync_add_and_fetch(&srv_conc_n_threads, -1);
++      trx->declared_to_be_inside_innodb = FALSE;
++      trx->n_tickets_to_enter_innodb = 0;
++      return;
++}
++#endif
++
+ void
+ srv_conc_enter_innodb(
+ /*==================*/
+@@ -1043,6 +1112,13 @@
+               return;
+       }
++#ifdef HAVE_ATOMIC_BUILTINS
++      if (srv_thread_concurrency_timer_based) {
++              srv_conc_enter_innodb_timer_based(trx);
++              return;
++      }
++#endif
++
+       os_fast_mutex_lock(&srv_conc_mutex);
+ retry:
+       if (trx->declared_to_be_inside_innodb) {
+@@ -1196,6 +1272,15 @@
+               return;
+       }
++      ut_ad(srv_conc_n_threads >= 0);
++#ifdef HAVE_ATOMIC_BUILTINS
++      if (srv_thread_concurrency_timer_based) {
++              __sync_add_and_fetch(&srv_conc_n_threads, 1);
++              trx->declared_to_be_inside_innodb = TRUE;
++              trx->n_tickets_to_enter_innodb = 1;
++              return;
++      }
++#endif
+       os_fast_mutex_lock(&srv_conc_mutex);
+       srv_conc_n_threads++;
+@@ -1227,8 +1312,16 @@
+               return;
+       }
++#ifdef HAVE_ATOMIC_BUILTINS
++      if (srv_thread_concurrency_timer_based) {
++              srv_conc_exit_innodb_timer_based(trx);
++              return;
++      }
++#endif
++
+       os_fast_mutex_lock(&srv_conc_mutex);
++      ut_ad(srv_conc_n_threads > 0);
+       srv_conc_n_threads--;
+       trx->declared_to_be_inside_innodb = FALSE;
+       trx->n_tickets_to_enter_innodb = 0;
+diff -ruN a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
+--- a/innobase/srv/srv0start.c 2009-05-06 15:38:01.000000000 +0900
++++ b/innobase/srv/srv0start.c 2009-05-06 17:22:26.000000000 +0900
+@@ -1040,6 +1040,11 @@
+               return(DB_ERROR);
+       }
++#ifdef HAVE_ATOMIC_BUILTINS
++      fprintf(stderr,
++              "InnoDB: use atomic builtins.\n");
++#endif
++
+       /* Since InnoDB does not currently clean up all its internal data
+          structures in MySQL Embedded Server Library server_end(), we
+          print an error message if someone tries to start up InnoDB a
+diff -ruN a/patch_info/innodb_thread_concurrency_timer_based.info b/patch_info/innodb_thread_concurrency_timer_based.info
+--- /dev/null  1970-01-01 09:00:00.000000000 +0900
++++ b/patch_info/innodb_thread_concurrency_timer_based.info    2009-05-06 17:17:12.000000000 +0900
+@@ -0,0 +1,6 @@
++File=thread_concurrency_timer_based.patch
++Name=Use InnoDB timer based concurrency throttling (backport from MySQL 5.4.0)
++Version=1.0
++Author=Percona <info@percona.com>
++License=GPL
++Comment
+diff -ruN a/sql/ha_innodb.cc b/sql/ha_innodb.cc
+--- a/sql/ha_innodb.cc 2009-05-06 15:38:01.000000000 +0900
++++ b/sql/ha_innodb.cc 2009-05-06 15:54:08.000000000 +0900
+@@ -152,6 +152,7 @@
+      innobase_open_files;
+ long innobase_read_io_threads, innobase_write_io_threads;
++my_bool innobase_thread_concurrency_timer_based;
+ long innobase_extra_rsegments;
+ longlong innobase_buffer_pool_size, innobase_log_file_size;
+@@ -1477,6 +1478,9 @@
+       srv_n_log_files = (ulint) innobase_log_files_in_group;
+       srv_log_file_size = (ulint) innobase_log_file_size;
++      srv_thread_concurrency_timer_based =
++              (ibool) innobase_thread_concurrency_timer_based;
++
+ #ifdef UNIV_LOG_ARCHIVE
+       srv_log_archive_on = (ulint) innobase_log_archive;
+ #endif /* UNIV_LOG_ARCHIVE */
+diff -ruN a/sql/ha_innodb.h b/sql/ha_innodb.h
+--- a/sql/ha_innodb.h  2009-05-06 15:38:01.000000000 +0900
++++ b/sql/ha_innodb.h  2009-05-06 15:55:50.000000000 +0900
+@@ -205,6 +205,7 @@
+ extern long innobase_buffer_pool_awe_mem_mb;
+ extern long innobase_file_io_threads, innobase_lock_wait_timeout;
+ extern long innobase_read_io_threads, innobase_write_io_threads;
++extern my_bool innobase_thread_concurrency_timer_based;
+ extern long innobase_extra_rsegments;
+ extern long innobase_force_recovery;
+ extern long innobase_open_files;
+diff -ruN a/sql/mysqld.cc b/sql/mysqld.cc
+--- a/sql/mysqld.cc    2009-05-06 15:38:01.000000000 +0900
++++ b/sql/mysqld.cc    2009-05-06 16:22:06.000000000 +0900
+@@ -5096,6 +5096,7 @@
+   OPT_INNODB_ADAPTIVE_CHECKPOINT,
+   OPT_INNODB_READ_IO_THREADS,
+   OPT_INNODB_WRITE_IO_THREADS,
++  OPT_INNODB_THREAD_CONCURRENCY_TIMER_BASED,
+   OPT_INNODB_EXTRA_RSEGMENTS,
+   OPT_INNODB_DICT_SIZE_LIMIT,
+   OPT_INNODB_ADAPTIVE_HASH_INDEX,
+@@ -5455,6 +5456,11 @@
+    "Number of background write I/O threads in InnoDB.",
+    (gptr*) &innobase_write_io_threads, (gptr*) &innobase_write_io_threads,
+    0, GET_LONG, REQUIRED_ARG, 1, 1, 64, 0, 0, 0},
++  {"innodb_thread_concurrency_timer_based", OPT_INNODB_THREAD_CONCURRENCY_TIMER_BASED,
++   "Use InnoDB timer based concurrency throttling. ",
++   (gptr*) &innobase_thread_concurrency_timer_based,
++   (gptr*) &innobase_thread_concurrency_timer_based,
++   0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+   {"innodb_extra_rsegments", OPT_INNODB_EXTRA_RSEGMENTS,
+    "Number of extra user rollback segments when create new database.",
+    (gptr*) &innobase_extra_rsegments, (gptr*) &innobase_extra_rsegments,
+diff -ruN a/sql/set_var.cc b/sql/set_var.cc
+--- a/sql/set_var.cc   2009-05-06 15:38:01.000000000 +0900
++++ b/sql/set_var.cc   2009-05-06 16:02:27.000000000 +0900
+@@ -1063,6 +1063,7 @@
+   {sys_innodb_adaptive_checkpoint.name, (char*) &sys_innodb_adaptive_checkpoint, SHOW_SYS},
+   {"innodb_read_io_threads", (char*) &innobase_read_io_threads, SHOW_LONG},
+   {"innodb_write_io_threads", (char*) &innobase_write_io_threads, SHOW_LONG},
++  {"innodb_thread_concurrency_timer_based", (char*) &innobase_thread_concurrency_timer_based, SHOW_MY_BOOL},
+   {"innodb_extra_rsegments", (char*) &innobase_extra_rsegments, SHOW_LONG},
+   {sys_innodb_dict_size_limit.name, (char*) &sys_innodb_dict_size_limit, SHOW_SYS},
+   {sys_innodb_io_pattern_trace.name, (char*) &sys_innodb_io_pattern_trace, SHOW_SYS},
diff --git a/mysql-mysql-test.patch b/mysql-mysql-test.patch
new file mode 100644 (file)
index 0000000..7fce8e0
--- /dev/null
@@ -0,0 +1,108 @@
+--- a/mysql-test/r/information_schema.result   2009-05-07 19:31:26.000000000 +0000
++++ b/mysql-test/r/information_schema.result   2009-05-07 19:32:59.000000000 +0000
+@@ -60,6 +60,7 @@
+ USER_STATISTICS
+ VIEWS
+ INNODB_IO_PATTERN
++INNODB_RSEG
+ columns_priv
+ db
+ func
+@@ -743,7 +744,7 @@
+ CREATE VIEW a1 (t_CRASHME) AS SELECT f1 FROM t_crashme GROUP BY f1;
+ CREATE VIEW a2 AS SELECT t_CRASHME FROM a1;
+ count(*)
+-109
++110
+ drop view a2, a1;
+ drop table t_crashme;
+ select table_schema,table_name, column_name from
+@@ -819,7 +820,7 @@
+ flush privileges;
+ SELECT table_schema, count(*) FROM information_schema.TABLES GROUP BY TABLE_SCHEMA;
+ table_schema  count(*)
+-information_schema    24
++information_schema    25
+ mysql 17
+ create table t1 (i int, j int);
+ create trigger trg1 before insert on t1 for each row
+@@ -1228,6 +1229,7 @@
+ USER_STATISTICS       USER
+ VIEWS TABLE_SCHEMA
+ INNODB_IO_PATTERN     SPACE
++INNODB_RSEG   RSEG_ID
+ SELECT t.table_name, c1.column_name
+ FROM information_schema.tables t
+ INNER JOIN
+@@ -1267,6 +1269,7 @@
+ USER_STATISTICS       USER
+ VIEWS TABLE_SCHEMA
+ INNODB_IO_PATTERN     SPACE
++INNODB_RSEG   RSEG_ID
+ SELECT MAX(table_name) FROM information_schema.tables;
+ MAX(table_name)
+ VIEWS
+@@ -1342,6 +1345,7 @@
+ INDEX_STATISTICS      information_schema.INDEX_STATISTICS     1
+ INNODB_BUFFER_POOL_CONTENT    information_schema.INNODB_BUFFER_POOL_CONTENT   1
+ INNODB_IO_PATTERN     information_schema.INNODB_IO_PATTERN    1
++INNODB_RSEG   information_schema.INNODB_RSEG  1
+ KEY_COLUMN_USAGE      information_schema.KEY_COLUMN_USAGE     1
+ PROCESSLIST   information_schema.PROCESSLIST  1
+ PROFILING     information_schema.PROFILING    1
+--- a/mysql-test/r/information_schema_db.result        2009-05-07 19:31:27.000000000 +0000
++++ b/mysql-test/r/information_schema_db.result        2009-05-07 19:35:01.000000000 +0000
+@@ -29,6 +29,7 @@
+ USER_STATISTICS
+ VIEWS
+ INNODB_IO_PATTERN
++INNODB_RSEG
+ show tables from INFORMATION_SCHEMA like 'T%';
+ Tables_in_information_schema (T%)
+ TABLES
+--- a/mysql-test/r/mysqlshow.result    2009-05-07 19:31:26.000000000 +0000
++++ b/mysql-test/r/mysqlshow.result    2009-05-07 19:36:32.000000000 +0000
+@@ -103,6 +103,7 @@
+ | USER_STATISTICS                       |
+ | VIEWS                                 |
+ | INNODB_IO_PATTERN                     |
++| INNODB_RSEG                           |
+ +---------------------------------------+
+ Database: INFORMATION_SCHEMA
+ +---------------------------------------+
+@@ -132,6 +133,7 @@
+ | USER_STATISTICS                       |
+ | VIEWS                                 |
+ | INNODB_IO_PATTERN                     |
++| INNODB_RSEG                           |
+ +---------------------------------------+
+ Wildcard: inf_rmation_schema
+ +--------------------+
+--- a/mysql-test/r/profiling.result    2009-05-28 19:39:42.000000000 +0000
++++ b/mysql-test/r/profiling.result    2009-05-28 19:40:14.000000000 +0000
+@@ -6,6 +6,8 @@
+ Variable_name Value
+ profiling     OFF
+ profiling_history_size        15
++profiling_server      OFF
++profiling_use_getrusage       OFF
+ select @@profiling;
+ @@profiling
+ 0
+@@ -16,12 +18,16 @@
+ Variable_name Value
+ profiling     OFF
+ profiling_history_size        100
++profiling_server      OFF
++profiling_use_getrusage       OFF
+ set session profiling = ON;
+ set session profiling_history_size=30;
+ show session variables like 'profil%';
+ Variable_name Value
+ profiling     ON
+ profiling_history_size        30
++profiling_server      OFF
++profiling_use_getrusage       OFF
+ select @@profiling;
+ @@profiling
+ 1
diff --git a/mysql-profiling_slow.patch b/mysql-profiling_slow.patch
new file mode 100644 (file)
index 0000000..703b8b7
--- /dev/null
@@ -0,0 +1,271 @@
+diff -r 92e70e675363 patch_info/profiling_slow.info
+--- /dev/null  Thu Jan 01 00:00:00 1970 +0000
++++ b/patch_info/profiling_slow.info   Mon Jun 01 00:50:00 2009 -0700
+@@ -0,0 +1,9 @@
++File=profiling_slow.info
++Name=profiling from SHOW PROFILE to slow.log
++Version=1.0
++Author=Percona <info@percona.com>
++License=GPL
++Comment=
++Changelog
++2009-05-18
++Initial implementation
+diff -r 92e70e675363 sql/log.cc
+--- a/sql/log.cc       Mon Jun 01 00:48:56 2009 -0700
++++ b/sql/log.cc       Mon Jun 01 00:50:00 2009 -0700
+@@ -2402,6 +2402,11 @@
+           tmp_errno=errno;
+       }
+     }
++
++#if defined(ENABLED_PROFILING) && defined(COMMUNITY_SERVER)
++    thd->profiling.print_current(&log_file);
++#endif
++
+     if (thd->db && strcmp(thd->db,db))
+     {                                         // Database changed
+       if (my_b_printf(&log_file,"use %s;\n",thd->db) == (uint) -1)
+diff -r 92e70e675363 sql/mysqld.cc
+--- a/sql/mysqld.cc    Mon Jun 01 00:48:56 2009 -0700
++++ b/sql/mysqld.cc    Mon Jun 01 00:50:00 2009 -0700
+@@ -5052,6 +5052,8 @@
+   OPT_PORT_OPEN_TIMEOUT,
+   OPT_MERGE,
+   OPT_PROFILING,
++  OPT_PROFILING_SERVER,
++  OPT_PROFILING_USE_GETRUSAGE,
+   OPT_SLOW_LOG,
+   OPT_SLOW_QUERY_LOG_FILE,
+   OPT_USE_GLOBAL_LONG_QUERY_TIME,
+@@ -5675,6 +5677,16 @@
+    (gptr*) &global_system_variables.profiling_history_size,
+    (gptr*) &max_system_variables.profiling_history_size,
+    0, GET_ULONG, REQUIRED_ARG, 15, 0, 100, 0, 0, 0},
++  {"profiling_server", OPT_PROFILING_SERVER,
++   "Enable profiling of all threads",
++   (gptr*) &global_system_variables.profiling_server,
++   (gptr*) &max_system_variables.profiling_server, 0, GET_BOOL,
++   OPT_ARG, 0, 0, 0, 0, 0, 0 },
++  {"profiling_use_getrusage", OPT_PROFILING_USE_GETRUSAGE,
++   "Enable getrusage function call for profiling",
++   (gptr*) &global_system_variables.profiling_use_getrusage,
++   (gptr*) &max_system_variables.profiling_use_getrusage, 0, GET_BOOL,
++   OPT_ARG, 0, 0, 0, 0, 0, 0 },
+ #endif
+   {"relay-log", OPT_RELAY_LOG,
+    "The location and name to use for relay logs.",
+diff -r 92e70e675363 sql/set_var.cc
+--- a/sql/set_var.cc   Mon Jun 01 00:48:56 2009 -0700
++++ b/sql/set_var.cc   Mon Jun 01 00:50:00 2009 -0700
+@@ -592,6 +592,10 @@
+                                       ulonglong(OPTION_PROFILING));
+ static sys_var_thd_ulong      sys_profiling_history_size("profiling_history_size",
+                                             &SV::profiling_history_size);
++static sys_var_thd_bool       sys_profiling_server("profiling_server",
++                                            &SV::profiling_server);
++static sys_var_thd_bool       sys_profiling_use_getrusage("profiling_use_getrusage",
++                                            &SV::profiling_use_getrusage);
+ #endif
+ /* Local state variables */
+@@ -764,6 +768,8 @@
+ #ifdef ENABLED_PROFILING
+   &sys_profiling,
+   &sys_profiling_history_size,
++  &sys_profiling_server,
++  &sys_profiling_use_getrusage,
+ #endif
+   &sys_pseudo_thread_id,
+   &sys_query_alloc_block_size,
+@@ -1094,6 +1100,8 @@
+ #ifdef ENABLED_PROFILING
+   {sys_profiling.name,        (char*) &sys_profiling,               SHOW_SYS},
+   {sys_profiling_history_size.name, (char*) &sys_profiling_history_size, SHOW_SYS},
++  {sys_profiling_server.name, (char*) &sys_profiling_server, SHOW_SYS},
++  {sys_profiling_use_getrusage.name, (char*) &sys_profiling_use_getrusage, SHOW_SYS},
+ #endif
+   {"protocol_version",        (char*) &protocol_version,            SHOW_INT},
+   {sys_query_alloc_block_size.name, (char*) &sys_query_alloc_block_size,
+diff -r 92e70e675363 sql/sql_class.h
+--- a/sql/sql_class.h  Mon Jun 01 00:48:56 2009 -0700
++++ b/sql/sql_class.h  Mon Jun 01 00:50:00 2009 -0700
+@@ -550,6 +550,8 @@
+   ulong optimizer_search_depth;
+   ulong preload_buff_size;
+   ulong profiling_history_size;
++  my_bool profiling_server;
++  my_bool profiling_use_getrusage;
+   ulong query_cache_type;
+   ulong log_slow_rate_limit;
+   ulong read_buff_size;
+diff -r 92e70e675363 sql/sql_profile.cc
+--- a/sql/sql_profile.cc       Mon Jun 01 00:48:56 2009 -0700
++++ b/sql/sql_profile.cc       Mon Jun 01 00:50:00 2009 -0700
+@@ -221,9 +221,22 @@
+ */
+ void PROF_MEASUREMENT::collect()
+ {
++  struct timespec tp;
+   time_usecs= (double) my_getsystime() / 10.0;  /* 1 sec was 1e7, now is 1e6 */
+ #ifdef HAVE_GETRUSAGE
+-  getrusage(RUSAGE_SELF, &rusage);
++  if ((profile->get_profiling())->enabled_getrusage())
++    getrusage(RUSAGE_SELF, &rusage);
++#endif
++
++#ifdef HAVE_CLOCK_GETTIME
++  if (!(clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp)))
++  {
++    cpu_time_usecs= tp.tv_sec*1000000000.0 + tp.tv_nsec;
++  } 
++  else
++  {
++    cpu_time_usecs= 0;
++  }
+ #endif
+ }
+@@ -341,7 +354,7 @@
+     finish_current_query();
+   }
+-  enabled= (((thd)->options & OPTION_PROFILING) != 0);
++  enabled= (((thd)->options & OPTION_PROFILING) != 0) || ( thd->variables.profiling_server );
+   if (! enabled) DBUG_VOID_RETURN;
+@@ -379,7 +392,8 @@
+     status_change("ending", NULL, NULL, 0);
+     if ((enabled) &&                                    /* ON at start? */
+-        ((thd->options & OPTION_PROFILING) != 0) &&   /* and ON at end? */
++        (((thd->options & OPTION_PROFILING) != 0) || 
++          (thd->variables.profiling_server)) &&   /* and ON at end? */
+         (current->query_source != NULL) &&
+         (! current->entries.is_empty()))
+     {
+@@ -480,6 +494,88 @@
+   DBUG_VOID_RETURN;
+ }
++bool PROFILING::enabled_getrusage()
++{
++  return thd->variables.profiling_use_getrusage;
++}
++
++/**
++  Print output for current query to file 
++*/
++
++int PROFILING::print_current(IO_CACHE *log_file)
++{
++  DBUG_ENTER("PROFILING::print_current");
++  ulonglong row_number= 0;
++  char query_time_buff[22+7];
++  char query_cpu_time_buff[22+7];
++
++  QUERY_PROFILE *query;
++  /* Get current query */
++  if (current == NULL)
++  {
++    DBUG_RETURN(0);
++  }
++
++  query= current;
++
++  my_b_printf(log_file, "# PROFILE_VALUES ");
++
++    void *entry_iterator;
++    PROF_MEASUREMENT *entry, *previous= NULL, *first= NULL;
++    /* ...and for each query, go through all its state-change steps. */
++    for (entry_iterator= query->entries.new_iterator();
++         entry_iterator != NULL;
++         entry_iterator= query->entries.iterator_next(entry_iterator),
++         previous=entry, row_number++)
++    {
++      entry= query->entries.iterator_value(entry_iterator);
++
++      /* Skip the first.  We count spans of fence, not fence-posts. */
++      if (previous == NULL) {first= entry; continue;}
++
++      if (thd->lex->orig_sql_command == SQLCOM_SHOW_PROFILE)
++      {
++        /*
++          We got here via a SHOW command.  That means that we stored
++          information about the query we wish to show and that isn't
++          in a WHERE clause at a higher level to filter out rows we
++          wish to exclude.
++
++          Because that functionality isn't available in the server yet,
++          we must filter here, at the wrong level.  Once one can con-
++          struct where and having conditions at the SQL layer, then this
++          condition should be ripped out.
++        */
++        if (thd->lex->profile_query_id == 0) /* 0 == show final query */
++        {
++          if (query != last)
++            continue;
++        }
++        else
++        {
++          if (thd->lex->profile_query_id != query->profiling_query_id)
++            continue;
++        }
++      }
++
++      snprintf(query_time_buff, sizeof(query_time_buff), "%.6f", (entry->time_usecs-previous->time_usecs)/(1000.0*1000));
++      snprintf(query_cpu_time_buff, sizeof(query_cpu_time_buff), "%.6f", (entry->cpu_time_usecs-previous->cpu_time_usecs)/(1000.0*1000*1000));
++      my_b_printf(log_file, "%s: %s (cpu: %s), ", previous->status, query_time_buff, query_cpu_time_buff);
++
++    }
++
++    my_b_printf(log_file, "\n");
++    if ((entry != NULL) && (first != NULL))
++    {
++      snprintf(query_time_buff, sizeof(query_time_buff), "%.6f", (entry->time_usecs-first->time_usecs)/(1000.0*1000));
++      snprintf(query_cpu_time_buff, sizeof(query_cpu_time_buff), "%.6f", (entry->cpu_time_usecs-first->cpu_time_usecs)/(1000.0*1000*1000));
++      my_b_printf(log_file, "# PROFILE_TOTALS Total: %s (cpu: %s)\n", query_time_buff, query_cpu_time_buff);
++    }
++
++  DBUG_RETURN(0);
++}
++
+ /**
+   Fill the information schema table, "query_profile", as defined in show.cc .
+   There are two ways to get to this function:  Selecting from the information
+diff -r 92e70e675363 sql/sql_profile.h
+--- a/sql/sql_profile.h        Mon Jun 01 00:48:56 2009 -0700
++++ b/sql/sql_profile.h        Mon Jun 01 00:50:00 2009 -0700
+@@ -193,6 +193,7 @@
+   unsigned int line;
+   double time_usecs;
++  double cpu_time_usecs;
+   char *allocated_status_memory;
+   void set_label(const char *status_arg, const char *function_arg, 
+@@ -243,6 +244,11 @@
+   /* Show this profile.  This is called by PROFILING. */
+   bool show(uint options);
++
++public:
++
++  inline PROFILING * get_profiling() { return profiling; };
++
+ };
+@@ -288,9 +294,11 @@
+   /* SHOW PROFILES */
+   bool show_profiles();
++  bool enabled_getrusage();
+   /* ... from INFORMATION_SCHEMA.PROFILING ... */
+   int fill_statistics_info(THD *thd, TABLE_LIST *tables, Item *cond);
++  int print_current(IO_CACHE *log_file);
+ };
+ #  endif /* HAVE_PROFILING */
This page took 0.27219 seconds and 4 git commands to generate.