From 05515cca1665544181b73e1dafc90a944df7af86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20M=C3=A4kel=C3=A4?= Date: Fri, 5 Apr 2019 11:04:04 +0300 Subject: [PATCH] MXS-2259: Limit size of client reads Given the assumption that queries are rarely 16MB long and that realistically the only time that happens is during a large dump of data, we can limit the size of a single read to at most one MariaDB/MySQL packet at a time. This change allows the network throttling to engage a lot sooner and reduces the maximum overshoot of throtting to 16MB. --- include/maxscale/dcb.h | 1 + server/core/dcb.cc | 4 ++-- .../protocol/MySQL/mariadbclient/mysql_client.cc | 12 +++++++++++- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/include/maxscale/dcb.h b/include/maxscale/dcb.h index c6c7052fb..82533417b 100644 --- a/include/maxscale/dcb.h +++ b/include/maxscale/dcb.h @@ -265,6 +265,7 @@ DCB* dcb_accept(DCB* listener); DCB* dcb_alloc(dcb_role_t, struct servlistener*); DCB* dcb_connect(struct server*, struct session*, const char*); int dcb_read(DCB*, GWBUF**, int); +int dcb_bytes_readable(DCB* dcb); int dcb_drain_writeq(DCB*); void dcb_close(DCB*); diff --git a/server/core/dcb.cc b/server/core/dcb.cc index 4770e7b05..3b72d4748 100644 --- a/server/core/dcb.cc +++ b/server/core/dcb.cc @@ -100,7 +100,6 @@ static inline DCB* dcb_find_in_list(DCB* dcb); static void dcb_stop_polling_and_shutdown(DCB* dcb); static bool dcb_maybe_add_persistent(DCB*); static inline bool dcb_write_parameter_check(DCB* dcb, GWBUF* queue); -static int dcb_bytes_readable(DCB* dcb); static int dcb_read_no_bytes_available(DCB* dcb, int nreadtotal); static int dcb_create_SSL(DCB* dcb, SSL_LISTENER* ssl); static int dcb_read_SSL(DCB* dcb, GWBUF** head); @@ -638,9 +637,10 @@ int dcb_read(DCB* dcb, * Find the number of bytes available for the DCB's socket * * @param dcb The DCB to read from + * * @return -1 on error, otherwise the total number of bytes available */ -static int dcb_bytes_readable(DCB* dcb) +int dcb_bytes_readable(DCB* dcb) { int bytesavailable; diff --git a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc index a4af1fc0f..68f87612f 100644 --- a/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc +++ b/server/modules/protocol/MySQL/mariadbclient/mysql_client.cc @@ -489,7 +489,10 @@ int gw_read_client_event(DCB* dcb) { max_bytes = 36; } - return_code = dcb_read(dcb, &read_buffer, max_bytes); + + const uint32_t max_single_read = GW_MYSQL_MAX_PACKET_LEN + MYSQL_HEADER_LEN; + return_code = dcb_read(dcb, &read_buffer, max_bytes > 0 ? max_bytes : max_single_read); + if (return_code < 0) { dcb_close(dcb); @@ -499,6 +502,13 @@ int gw_read_client_event(DCB* dcb) return return_code; } + if (nbytes_read == max_single_read && dcb_bytes_readable(dcb) > 0) + { + // We read a maximally long packet, route it first. This is done in case there's a lot more data + // waiting and we have to start throttling the reads. + poll_fake_read_event(dcb); + } + return_code = 0; switch (protocol->protocol_auth_state)