Bug #69325 | MySQL uses significantly more memory for ALTER TABLE than expected | ||
---|---|---|---|
Submitted: | 27 May 2013 9:22 | Modified: | 19 Dec 2013 15:25 |
Reporter: | Justin Swanhart | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: InnoDB storage engine | Severity: | S3 (Non-critical) |
Version: | 5.6.11 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | ALTER TABLE, innodb_sort_buffer_size, Memory |
[27 May 2013 9:22]
Justin Swanhart
[27 May 2013 10:32]
MySQL Verification Team
So we now have a situation where this is possible to consume inordinate amounts of memory with default settings (assuming sufficient file descriptors). ----- drop table if exists t1; create table t1(a int,b int,key(a))engine=innodb partition by hash(a) partitions 8192; alter table t1 add key(b); -----
[27 May 2013 14:52]
MySQL Verification Team
Documentation here: http://dev.mysql.com/doc/refman/5.6/en/innodb- parameters.html#sysvar_innodb_sort_buffer_size We need to document the memory requirement for DDL statements, keeping in mind partitions, and multiple DDL operations in a single SQL. Then, we could attempt to reduce the overall memory footprint. Alloc/dealloc after each partition is processed? -------------------------------------------------------------------------------- n time(i) total(B) useful-heap(B) extra-heap(B) stacks(B) -------------------------------------------------------------------------------- 317 31,220,578,990 21,219,106,816 21,219,106,816 0 0 100.00% (21,219,106,816B) (page allocation syscalls) mmap/mremap/brk, --alloc-fns, etc. ->99.75% (21,166,043,136B) 0x36798EDFB9: mmap (syscall-template.S:82) | ->95.04% (20,166,115,328B) 0x934380: os_mem_alloc_large(unsigned long*) (os0proc.cc:158) | | ->94.38% (20,025,606,144B) 0x974DCA: row_log_allocate(dict_index_t*, dict_table_t*, bool, dtuple_t const*, unsigned long const*) (row0log.cc:2618) | | | ->94.38% (20,025,606,144B) 0x6170F9: prepare_inplace_alter_table_dict(Alter_inplace_info*, TABLE const*, TABLE const*, char const*, unsigned long, unsigned long, unsigned long, bool, bool) (handler0alter.cc:2952) | | | ->94.38% (20,025,606,144B) 0x905112: ha_innobase::prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) (handler0alter.cc:4053) | | | ->94.38% (20,025,606,144B) 0xAB5700: ha_partition::prepare_inplace_alter_table(TABLE*, Alter_inplace_info*) (ha_partition.cc:7987) | | | ->94.38% (20,025,606,144B) 0x60EFB0: mysql_inplace_alter_table(THD*, TABLE_LIST*, TABLE*, TABLE*, Alter_inplace_info*, enum_alter_inplace_result, MDL_request*, Alter_table_ctx*) [clone .isra.91] (sql_table.cc:6515) | | | ->94.38% (20,025,606,144B) 0x7BEE66: mysql_alter_table(THD*, char*, char*, st_ha_create_information*, TABLE_LIST*, Alter_info*, unsigned int, st_order*, bool) (sql_table.cc:8271) | | | ->94.38% (20,025,606,144B) 0x857BF3: Sql_cmd_alter_table::execute(THD*) (sql_alter.cc:316) | | | ->94.38% (20,025,606,144B) 0x7693C7: mysql_execute_command(THD*) (sql_parse.cc:4642) | | | ->94.38% (20,025,606,144B) 0x76B056: mysql_parse(THD*, char*, unsigned int, Parser_state*) (sql_parse.cc:5213) | | | ->94.38% (20,025,606,144B) 0x76BC7F: dispatch_command(enum_server_command, THD*, char*, unsigned int) (sql_parse.cc:1324) | | | ->94.38% (20,025,606,144B) 0x737DCD: do_handle_one_connection(THD*) (sql_connect.cc:983) | | | ->94.38% (20,025,606,144B) 0x737E4E: handle_one_connection (sql_connect.cc:899) | | | ->94.38% (20,025,606,144B) 0xA3FD34: pfs_spawn_thread (pfs.cc:1924) | | | ->94.38% (20,025,606,144B) 0x3679C07D12: start_thread (pthread_create.c:309) | | | ->94.38% (20,025,606,144B) 0x36798F168B: clone (clone.S:115)
[28 May 2013 16:39]
Mark Callaghan
Can the docs get updated to explain this case? Is this only an issue for fast-index-create?
[19 Dec 2013 15:25]
Daniel Price
Noted in 5.6.16, 5.7.4 changelog: An online "ALTER TABLE" operation would consume more memory than expected. During an online "ALTER TABLE" operation, an online log buffer containing a head and tail buffer is created for each index that is created or rebuilt. The tail buffer is the writer context and is only required for concurrent write operations on an index while the "ALTER TABLE" operation is in progress. The head buffer is the reader context and is only required during the log apply phase. To reduce memory consumption, the tail buffer is now allocated when the first DML statement is run on the index, and the head buffer is only allocated in the log apply phase and freed afterwards.
[3 Feb 2014 11:48]
Laurynas Biveinis
5.6$ bzr log -r 5702 ------------------------------------------------------------ revno: 5702 committer: Thirunarayanan B<thirunarayanan.balathandayuth@oracle.com> branch nick: r-5.6 timestamp: Thu 2013-12-19 11:44:13 +0530 message: Bug #16868967 MYSQL USES SIGNIFICANTLY MORE MEMORY FOR ALTER TABLE THAN EXPECTED Problem: During online alter table, an online log buffer would be created for index that is being rebuilt or created. This online log contains two buffers - head and tail. Alter table takes lot of memory than expected even there is no concurrent write for index. But Both head and tail buffer will be useful when there is a concurrent write on the index. If there are many partitions involved, it is unlikely that all the partitions would be modified concurrently. Solution: Allocate the tail buffer only when first DML statement happens on the index. Allocate the head buffer only in apply phase and freed at the end of the apply phase. Approved by Marko rb#3850
[4 Jan 2016 13:01]
Daniel Price
Posted by developer: The formula for estimating memory consumption has been corrected in the documentation. http://dev.mysql.com/doc/refman/5.6/en/innodb-parameters.html#sysvar_innodb_sort_buffer_si...