From 548413824b85fa0550c8d9a297546b80ed1643e1 Mon Sep 17 00:00:00 2001 From: Kristofer Pettersson <kpettersson@mysql.com> Date: Thu, 24 Jul 2008 22:38:44 +0200 Subject: [PATCH] Bug#38002 table_cache consumes too much memory with blobs Tables in the table definition cache are keeping a cache buffer for blob fields which can consume a lot of memory. This patch introduces a maximum size threshold for these buffers. sql/sql_base.cc: Added function free_field_buffers_larger_than to reclaim memory from blob field buffers too large to be cached. sql/table.cc: Added function free_field_buffers_larger_than --- sql/field.h | 2 +- sql/mysql_priv.h | 1 + sql/sql_base.cc | 2 ++ sql/table.cc | 22 ++++++++++++++++++++++ sql/table.h | 3 +++ 5 files changed, 29 insertions(+), 1 deletion(-) diff --git a/sql/field.h b/sql/field.h index 7d312dbd2b8..8e00cf013dc 100644 --- a/sql/field.h +++ b/sql/field.h @@ -13,7 +13,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - /* Because of the function new_field() all field classes that have static variables must declare the size_of() member function. @@ -1669,6 +1668,7 @@ class Field_blob :public Field_longstr { } int reset(void) { bzero(ptr, packlength+sizeof(uchar*)); return 0; } void reset_fields() { bzero((uchar*) &value,sizeof(value)); } + uint32 get_field_buffer_size(void) { return value.alloced_length(); } #ifndef WORDS_BIGENDIAN static #endif diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index e150ffd18f8..f6ba5fc9739 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -2130,6 +2130,7 @@ int writefrm(const char* name, const uchar* data, size_t len); int closefrm(TABLE *table, bool free_share); int read_string(File file, uchar* *to, size_t length); void free_blobs(TABLE *table); +void free_field_buffers_larger_than(TABLE *table, uint32 size); int set_zone(int nr,int min_zone,int max_zone); ulong convert_period_to_month(ulong period); ulong convert_month_to_period(ulong month); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index d25057789ac..39dd815e738 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -1369,6 +1369,8 @@ bool close_thread_table(THD *thd, TABLE **table_ptr) DBUG_ASSERT(!table->is_children_attached()); /* Free memory and reset for next loop */ + free_field_buffers_larger_than(table,MAX_TDC_BLOB_SIZE); + table->file->ha_reset(); table->in_use=0; if (unused_tables) diff --git a/sql/table.cc b/sql/table.cc index ebf3dfd748e..58cbde74822 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1999,6 +1999,28 @@ void free_blobs(register TABLE *table) } +/** + Reclaim temporary blob storage which is bigger than + a threshold. + + @param table A handle to the TABLE object containing blob fields + @param size The threshold value. + +*/ + +void free_field_buffers_larger_than(TABLE *table, uint32 size) +{ + uint *ptr, *end; + for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ; + ptr != end ; + ptr++) + { + Field_blob *blob= (Field_blob*) table->field[*ptr]; + if (blob->get_field_buffer_size() > size) + blob->free(); + } +} + /* Find where a form starts */ /* if formname is NullS then only formnames is read */ diff --git a/sql/table.h b/sql/table.h index 75ddaf69c10..da0e089794f 100644 --- a/sql/table.h +++ b/sql/table.h @@ -935,6 +935,9 @@ typedef struct st_schema_table #define VIEW_CHECK_ERROR 1 #define VIEW_CHECK_SKIP 2 +/** The threshold size a blob field buffer before it is freed */ +#define MAX_TDC_BLOB_SIZE 65536 + struct st_lex; class select_union; class TMP_TABLE_PARAM; -- 2.30.9