summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorKristofer Pettersson <kpettersson@mysql.com>2008-07-24 22:38:44 +0200
committerKristofer Pettersson <kpettersson@mysql.com>2008-07-24 22:38:44 +0200
commit5c1f8d1836554f6978b8fe84acb3e3e1f207bca1 (patch)
tree87fb26d4be11fe0d8b5ddd517de3bd328ea5b6fc /sql
parent58daa8d50a05e863ed6f24646b05d600070646af (diff)
downloadmariadb-git-5c1f8d1836554f6978b8fe84acb3e3e1f207bca1.tar.gz
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.
Diffstat (limited to 'sql')
-rw-r--r--sql/field.h2
-rw-r--r--sql/mysql_priv.h1
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/table.cc22
-rw-r--r--sql/table.h3
5 files changed, 29 insertions, 1 deletions
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 @@ public:
}
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;