Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MDEV-35889 set information_schema.system_variables NUMERIC_MIN_VALUE for the innodb_buffer_pool_size system variable based on innodb_page_size #3777

Open
wants to merge 1 commit into
base: 10.5
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions mysql-test/suite/innodb/t/restart.test
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,11 @@ let $wait_condition =

--disable_cursor_protocol
SELECT @@innodb_buffer_pool_size INTO @innodb_buffer_pool_size_orig;
SELECT CEILING((256 + 64) * @@innodb_page_size / 1048576) * 1048576 INTO @min_pool_size;
SELECT CAST(NUMERIC_MIN_VALUE AS UNSIGNED) INTO @min_pool_size FROM information_schema.system_variables WHERE variable_name='INNODB_BUFFER_POOL_SIZE';
SET @out_of_bounds_pool_size=@min_pool_size - @@innodb_buffer_pool_chunk_size;
--enable_cursor_protocol
--error ER_WRONG_VALUE_FOR_VAR
EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@min_pool_size -1);
EXECUTE IMMEDIATE 'SET GLOBAL innodb_buffer_pool_size = ?' USING (@out_of_bounds_pool_size);

SHOW WARNINGS;

Expand Down
3 changes: 3 additions & 0 deletions sql/set_var.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1117,6 +1117,9 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)

mysql_mutex_lock(&LOCK_global_system_variables);

if (var->cast_pluginvar())
plugin_opt_set_limits(&var->option, var->cast_mysql_sys_var());

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do you need that?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During plugin initialization the mysq_sys_var is copied to var->option giving the value of 2M for the variable:

Old value = 0
New value = 2097152
0x000000000090d6be in plugin_opt_set_limits (options=0x732ef70, opt=0x1f6ba90 <mysql_sysvar_buffer_pool_size>)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:3730
3730	    OPTION_SET_LIMITS(GET_ULL, options, (sysvar_ulonglong_t*) opt);
(rr) p options
$4 = (my_option *) 0x732ef70
(rr) p *options
$5 = {name = 0x732ef28 "innodb_buffer_pool_size", id = 0, 
  comment = 0x180465a "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", 
  value = 0x2132a58 <global_system_variables>, u_max_value = 0x0, typelib = 0x0, var_type = 8, arg_type = NO_ARG, def_value = 134217728, 
  min_value = 2097152, max_value = 0, sub_size = 0, block_size = 0, app_type = 0x732ef40}
(rr) bt
#0  0x000000000090d6be in plugin_opt_set_limits (options=0x732ef70, opt=0x1f6ba90 <mysql_sysvar_buffer_pool_size>)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:3730
#1  0x000000000090cc89 in sys_var_pluginvar::sys_var_pluginvar (this=0x732ef40, chain=0x7ffc59ce9360, 
    name_arg=0x732ef28 "innodb_buffer_pool_size", p=0x731fdc0, pv=0x1f6ba90 <mysql_sysvar_buffer_pool_size>, substitute=0x0)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:3486
#2  0x000000000091097a in test_plugin_options (tmp_root=0x7ffc59ce99a0, tmp=0x731fdc0, argc=0x2137bc8 <remaining_argc>, argv=0x72dac88)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:4244
#3  0x000000000090741b in plugin_initialize (tmp_root=0x7ffc59ce99a0, plugin=0x731fdc0, argc=0x2137bc8 <remaining_argc>, argv=0x72dac88, 
    options_only=false) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:1497
#4  0x0000000000906b9e in plugin_init (argc=0x2137bc8 <remaining_argc>, argv=0x72dac88, flags=0)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:1762
#5  0x000000000077fe63 in init_server_components () at /home/dan/repos/mariadb-server-10.5-quick/sql/mysqld.cc:4954
#6  0x000000000077c60c in mysqld_main (argc=9, argv=0x72dac88) at /home/dan/repos/mariadb-server-10.5-quick/sql/mysqld.cc:5562
#7  0x0000000000778bb2 in main (argc=8, argv=0x7ffc59ceb5a8) at /home/dan/repos/mariadb-server-10.5-quick/sql/main.cc:25
(rr) c
Continuing.

When InnoDB initializes, it changes it min_value because the innodb_page_size in this case is 64k.

Thread 1 hit Hardware watchpoint 1: -location mysql_sysvar_buffer_pool_size.min_val

Old value = 2097152
New value = 20971520
innodb_init_params () at /home/dan/repos/mariadb-server-10.5-quick/storage/innobase/handler/ha_innodb.cc:3551
3551		if (innobase_buffer_pool_size < MYSQL_SYSVAR_NAME(buffer_pool_size).min_val) {
(rr) bt
#0  innodb_init_params () at /home/dan/repos/mariadb-server-10.5-quick/storage/innobase/handler/ha_innodb.cc:3551
#1  0x00000000010d2368 in innodb_init (p=0x73ea3e8) at /home/dan/repos/mariadb-server-10.5-quick/storage/innobase/handler/ha_innodb.cc:4028
#2  0x0000000000c7af11 in ha_initialize_handlerton (plugin_=0x731fdc0) at /home/dan/repos/mariadb-server-10.5-quick/sql/handler.cc:648
#3  0x0000000000907b62 in plugin_do_initialize (plugin=0x731fdc0, state=@0x7ffc59ce93c8: 4)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:1453
#4  0x0000000000907481 in plugin_initialize (tmp_root=0x7ffc59ce99a0, plugin=0x731fdc0, argc=0x2137bc8 <remaining_argc>, argv=0x72dac88, 
    options_only=false) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:1507
#5  0x0000000000906b9e in plugin_init (argc=0x2137bc8 <remaining_argc>, argv=0x72dac88, flags=0)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:1762
#6  0x000000000077fe63 in init_server_components () at /home/dan/repos/mariadb-server-10.5-quick/sql/mysqld.cc:4954
#7  0x000000000077c60c in mysqld_main (argc=9, argv=0x72dac88) at /home/dan/repos/mariadb-server-10.5-quick/sql/mysqld.cc:5562
#8  0x0000000000778bb2 in main (argc=8, argv=0x7ffc59ceb5a8) at /home/dan/repos/mariadb-server-10.5-quick/sql/main.cc:25
(rr) c

Performing and information_schema select returns the original 2M value, despite the current situtation that the minimum is now 20M.

Continuing.
2025-01-28 16:18:35 0 [Note] InnoDB: innodb_page_size=65536
2025-01-28 16:18:35 0 [Note] InnoDB: !!!!!!!! UNIV_DEBUG switched on !!!!!!!!!
2025-01-28 16:18:35 0 [Note] InnoDB: Uses event mutexes
2025-01-28 16:18:35 0 [Note] InnoDB: Compressed tables use zlib 1.3.1.zlib-ng
2025-01-28 16:18:35 0 [Note] InnoDB: Number of pools: 1
2025-01-28 16:18:35 0 [Note] InnoDB: Using AVX512 instructions
2025-01-28 16:18:35 0 [Warning] InnoDB: Linux Native AIO disabled.
2025-01-28 16:18:35 0 [Note] InnoDB: Initializing buffer pool, total size = 134217728, chunk size = 134217728
2025-01-28 16:18:35 0 [Note] InnoDB: Completed initialization of buffer pool
2025-01-28 16:18:35 0 [Note] InnoDB: 128 rollback segments are active.
2025-01-28 16:18:35 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2025-01-28 16:18:35 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2025-01-28 16:18:35 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2025-01-28 16:18:35 0 [Note] InnoDB: 10.5.28 started; log sequence number 45554; transaction id 20
2025-01-28 16:18:35 0 [Note] Plugin 'FEEDBACK' is disabled.
2025-01-28 16:18:35 0 [Note] InnoDB: Loading buffer pool(s) from /tmp/build-mariadb-server-10.5-quick-debug-datadir/ib_buffer_pool
2025-01-28 16:18:35 0 [Note] InnoDB: Buffer pool(s) load completed at 250128 16:18:35
2025-01-28 16:18:35 0 [Note] Reading of all Master_info entries succeeded
2025-01-28 16:18:35 0 [Note] Added new Master_info '' to hash table
2025-01-28 16:18:35 0 [Note] sql/mariadbd: ready for connections.
Version: '10.5.28-MariaDB-debug'  socket: '/tmp/build-mariadb-server-10.5-quick-debug.sock'  port: 0  Source distribution
[New Thread 112246.112319]
[New Thread 112246.112249]
[New Thread 112246.112251]
[New Thread 112246.112252]
[New Thread 112246.112253]
[New Thread 112246.112254]
[New Thread 112246.112255]
[New Thread 112246.112256]
[New Thread 112246.112257]
[Switching to Thread 112246.112319]

Thread 13 hit Breakpoint 3, sys_var_pluginvar::cast_pluginvar (this=0x732ef40) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:317
317	  sys_var_pluginvar *cast_pluginvar() override { return this; }
(rr) p option
$6 = {name = 0x732ef28 "innodb_buffer_pool_size", id = 0, 
  comment = 0x180465a "The size of the memory buffer InnoDB uses to cache data and indexes of its tables.", 
  value = 0x2132a58 <global_system_variables>, u_max_value = 0x0, typelib = 0x0, var_type = 8, arg_type = REQUIRED_ARG, def_value = 134217728, 
  min_value = 2097152, max_value = 9223372036854775807, sub_size = 0, block_size = 1048576, app_type = 0x732ef40}
(rr) bt
#0  sys_var_pluginvar::cast_pluginvar (this=0x732ef40) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:317
#1  0x000000000090c26f in find_sys_var (thd=0x7fbdec002258, str=0x7fbdec019fa8 "innodb_buffer_pool_size", length=23, throw_error=false)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_plugin.cc:2971
#2  0x0000000000d29135 in get_system_var (thd=0x7fbdec002258, var_type=SHOW_OPT_DEFAULT, name=0x7fbe177644b0, 
    component=0x18a8000 <null_clex_str>) at /home/dan/repos/mariadb-server-10.5-quick/sql/item_func.cc:6609
#3  0x00000000008bbe09 in LEX::make_item_sysvar (this=0x7fbdec006348, thd=0x7fbdec002258, type=SHOW_OPT_DEFAULT, name=0x7fbe177644b0, 
    component=0x18a8000 <null_clex_str>) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_lex.cc:7989
#4  0x0000000000beb7f2 in LEX::make_item_sysvar (this=0x7fbdec006348, thd=0x7fbdec002258, type=SHOW_OPT_DEFAULT, name=0x7fbe177644b0)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_lex.h:4218
#5  0x0000000000bd16a6 in MYSQLparse (thd=0x7fbdec002258) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_yacc.yy:11401
#6  0x00000000008fcbe3 in parse_sql (thd=0x7fbdec002258, parser_state=0x7fbe17765838, creation_ctx=0x0, do_pfs_digest=true)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_parse.cc:10683
#7  0x00000000008e3d5a in mysql_parse (thd=0x7fbdec002258, 
    rawbuf=0x7fbdec0198b0 "SELECT @@innodb_buffer_pool_size, @@innodb_page_size, information_schema.system_variables.NUMERIC_MIN_VALUE FROM information_schema.system_variables where information_schema.system_variables.variable_"..., length=230, parser_state=0x7fbe17765838, 
    is_com_multi=false, is_next_command=false) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_parse.cc:8203
#8  0x00000000008e06ed in dispatch_command (command=COM_QUERY, thd=0x7fbdec002258, 
    packet=0x7fbdec00e7b9 "SELECT @@innodb_buffer_pool_size, @@innodb_page_size, information_schema.system_variables.NUMERIC_MIN_VALUE FROM information_schema.system_variables where information_schema.system_variables.variable_"..., packet_length=230, is_com_multi=false, 
    is_next_command=false) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_parse.cc:1891
#9  0x00000000008e4dd3 in do_command (thd=0x7fbdec002258) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_parse.cc:1375
#10 0x0000000000a9e9f8 in do_handle_one_connection (connect=0x79946c8, put_in_cache=true)
    at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_connect.cc:1386
#11 0x0000000000a9e790 in handle_one_connection (arg=0x79946c8) at /home/dan/repos/mariadb-server-10.5-quick/sql/sql_connect.cc:1298
#12 0x0000000000fe30ec in pfs_spawn_thread (arg=0x78986c8) at /home/dan/repos/mariadb-server-10.5-quick/storage/perfschema/pfs.cc:2201
#13 0x00007fbe2c47d148 in start_thread () from /lib64/libc.so.6
#14 0x00007fbe2c500ed4 in clone () from /lib64/libc.so.6

At some point to make information_schema.sysvars correct we need to pull the new mysql_sysvar_buffer_pool_size.min_value into the options used by the information schema. As the innodb_buffer_pool_size is dynamic, it makes sense to have a value in the information_schema that reflects its current value.

// SESSION_VALUE
store_var(fields[1], var, OPT_SESSION, &strbuf);

Expand Down
1 change: 1 addition & 0 deletions sql/set_var.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ class sys_var: protected Value_source // for double_from_string_with_check
of sys_var_pluginvar, and 0 otherwise.
*/
virtual sys_var_pluginvar *cast_pluginvar() { return 0; }
virtual const struct st_mysql_sys_var *cast_mysql_sys_var() const { return nullptr; }

bool check(THD *thd, set_var *var);
const uchar *value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base) const;
Expand Down
9 changes: 9 additions & 0 deletions sql/sql_plugin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ class sys_var_pluginvar: public sys_var, public Sql_alloc
st_plugin_int *p, st_mysql_sys_var *plugin_var_arg,
const char *substitute);
sys_var_pluginvar *cast_pluginvar() override { return this; }
virtual const struct st_mysql_sys_var *cast_mysql_sys_var() const override { return plugin_var; }
uchar* real_value_ptr(THD *thd, enum_var_type type) const;
TYPELIB* plugin_var_typelib(void) const;
const uchar* do_value_ptr(THD *thd, enum_var_type type, const LEX_CSTRING *base) const;
Expand Down Expand Up @@ -3683,14 +3684,22 @@ bool sys_var_pluginvar::global_update(THD *thd, set_var *var)

#define OPTION_SET_LIMITS(type, options, opt) \
options->var_type= type; \
assert((opt)->def_val >= (opt)->min_val); \
assert((opt)->def_val <= (opt)->max_val); \
options->def_value= (opt)->def_val; \
assert((opt)->min_val <= (opt)->max_val); \
options->min_value= (opt)->min_val; \
options->max_value= (opt)->max_val; \
assert((opt)->blk_sz == 0 || ((opt)->min_val % (opt)->blk_sz) == 0); \
assert((opt)->blk_sz == 0 || ((opt)->max_val % (opt)->blk_sz) == 0); \
options->block_size= (long) (opt)->blk_sz

#define OPTION_SET_LIMITS_DOUBLE(options, opt) \
options->var_type= GET_DOUBLE; \
assert((opt)->def_val >= (opt)->min_val); \
assert((opt)->def_val <= (opt)->max_val); \
options->def_value= (longlong) getopt_double2ulonglong((opt)->def_val); \
assert((opt)->min_val <= (opt)->max_val); \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's the server code, you could use DBUG_ASSERT here, as far as I can see

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note, might need to drop the max divisible by block size - myisam_max_sort_file_size fails this as would other with a max value divisible by a power of two value.

(gdb) p *(sysvar_ulonglong_t*) opt
$4 = {flags = 132, name = 0x1793cda "max_sort_file_size", 
  comment = 0x187e40a "Don't use the fast sort index method to created index if the temporary file would get bigger than this", check = 0x9129c0 <check_func_longlong(THD*, st_mysql_sys_var*, void*, st_mysql_value*)>, 
  update = 0x912b80 <update_func_longlong(THD*, st_mysql_sys_var*, void*, void const*)>, 
  value = 0x1f78888 <myisam_max_temp_length>, def_val = 9223372036853727232, min_val = 0, 
  max_val = 9223372036854775807, blk_sz = 1048576}
(gdb) p (((sysvar_ulonglong_t*) opt)->max_val % ((sysvar_ulonglong_t*) opt)->blk_sz)
$5 = 1048575
(gdb) p 9223372036854775807 % 1048576
$6 = 1048575
(gdb) p 9223372036854775808 % 1048576
$7 = 0

options->min_value= (longlong) getopt_double2ulonglong((opt)->min_val); \
options->max_value= getopt_double2ulonglong((opt)->max_val); \
options->block_size= (long) (opt)->blk_sz;
Expand Down