summaryrefslogtreecommitdiff
path: root/sql/sql_cache.cc
diff options
context:
space:
mode:
authorDmitry Shulga <Dmitry.Shulga@Sun.COM>2010-09-16 17:38:13 +0700
committerDmitry Shulga <Dmitry.Shulga@Sun.COM>2010-09-16 17:38:13 +0700
commitdeacb7c8ab3dc0bf097ec7598dcfa84007e16fc4 (patch)
tree53ee44a010c3a3787074d14e894edbed17daaddc /sql/sql_cache.cc
parent5f2bfccec41d0b5d693355628a1c51c66b47b75b (diff)
parent0c91b53d10ad74fd26a2e3ba565d117539d8983c (diff)
downloadmariadb-git-deacb7c8ab3dc0bf097ec7598dcfa84007e16fc4.tar.gz
Auto-merge from mysql-5.1-bugteam for bug#42503.
Diffstat (limited to 'sql/sql_cache.cc')
-rw-r--r--sql/sql_cache.cc59
1 files changed, 54 insertions, 5 deletions
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index d6dc9edc502..7b288948885 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -1346,6 +1346,55 @@ end:
}
+/**
+ Send a single memory block from the query cache.
+
+ Respects the client/server protocol limits for the
+ size of the network packet, and splits a large block
+ in pieces to ensure that individual piece doesn't exceed
+ the maximal allowed size of the network packet (16M).
+
+ @param[in] net NET handler
+ @param[in] packet packet to send
+ @param[in] len packet length
+
+ @return Operation status
+ @retval FALSE On success
+ @retval TRUE On error
+*/
+static bool
+send_data_in_chunks(NET *net, const uchar *packet, ulong len)
+{
+ /*
+ On the client we may require more memory than max_allowed_packet
+ to keep, both, the truncated last logical packet, and the
+ compressed next packet. This never (or in practice never)
+ happens without compression, since without compression it's very
+ unlikely that a) a truncated logical packet would remain on the
+ client when it's time to read the next packet b) a subsequent
+ logical packet that is being read would be so large that
+ size-of-new-packet + size-of-old-packet-tail >
+ max_allowed_packet. To remedy this issue, we send data in 1MB
+ sized packets, that's below the current client default of 16MB
+ for max_allowed_packet, but large enough to ensure there is no
+ unnecessary overhead from too many syscalls per result set.
+ */
+ static const ulong MAX_CHUNK_LENGTH= 1024*1024;
+
+ while (len > MAX_CHUNK_LENGTH)
+ {
+ if (net_real_write(net, packet, MAX_CHUNK_LENGTH))
+ return TRUE;
+ packet+= MAX_CHUNK_LENGTH;
+ len-= MAX_CHUNK_LENGTH;
+ }
+ if (len && net_real_write(net, packet, len))
+ return TRUE;
+
+ return FALSE;
+}
+
+
/*
Check if the query is in the cache. If it was cached, send it
to the user.
@@ -1655,11 +1704,11 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d",
ALIGN_SIZE(sizeof(Query_cache_result)))));
Query_cache_result *result = result_block->result();
- if (net_real_write(&thd->net, result->data(),
- result_block->used -
- result_block->headers_len() -
- ALIGN_SIZE(sizeof(Query_cache_result))))
- break; // Client aborted
+ if (send_data_in_chunks(&thd->net, result->data(),
+ result_block->used -
+ result_block->headers_len() -
+ ALIGN_SIZE(sizeof(Query_cache_result))))
+ break; // Client aborted
result_block = result_block->next;
thd->net.pkt_nr= query->last_pkt_nr; // Keep packet number updated
} while (result_block != first_result_block);