Skip to content

Commit 97eab1b

Browse files
authored
Merge pull request #5825 from sysown/v3.0_partition-fairness
Promote longest-waiting B session via max_connect_time fold
2 parents b5b4d8b + aa0f136 commit 97eab1b

2 files changed

Lines changed: 26 additions & 1 deletion

File tree

include/Base_Thread.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ class Base_Thread {
6666
// Below this attempt count a tick carries no signal: gate state and
6767
// streak are left untouched. Avoids "2/2 NULL = 100% stressed" noise.
6868
static constexpr unsigned int PARTITION_GATE_MIN_ATTEMPTS = 4;
69+
static constexpr unsigned int PARTITION_FAIRNESS_MIN_B = 4;
6970

7071
// Called by sessions inside this worker at the get_MyConn_from_pool()
7172
// call site to feed the gate.

lib/Base_Thread.cpp

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,23 +285,37 @@ void Base_Thread::ProcessAllSessions_Partition() {
285285
size_t running_end = 0;
286286
size_t idle_begin = mysql_sessions->len;
287287
size_t idx = 0;
288+
size_t oldest_idx = SIZE_MAX;
289+
unsigned long long oldest_mct = UINT64_MAX;
288290

289291
while (idx < idle_begin) {
290292
S* s = static_cast<S*>(mysql_sessions->index(idx));
291293

292294
const bool has_be = (s->mybe && s->mybe->server_myds);
293-
const bool is_B = has_be && (s->mybe->server_myds->max_connect_time != 0);
295+
const unsigned long long mct = has_be ? s->mybe->server_myds->max_connect_time : 0ULL;
296+
const bool is_B = (mct != 0);
294297
const bool is_A = !is_B && has_be && (s->mybe->server_myds->myconn != nullptr) && (s->status != WAITING_CLIENT_DATA);
295298

296299
if (is_A) {
297300
if (idx != running_end) {
301+
// Keep the tracked oldest valid: the B session at running_end is
302+
// about to be swapped to idx.
303+
if (oldest_idx == running_end) oldest_idx = idx;
298304
void* p = mysql_sessions->pdata[idx];
299305
mysql_sessions->pdata[idx] = mysql_sessions->pdata[running_end];
300306
mysql_sessions->pdata[running_end] = p;
301307
}
302308
++running_end;
303309
++idx;
304310
} else if (is_B) {
311+
// Key on max_connect_time: it was already loaded for the is_B test
312+
// above, so this is a register compare with no extra memory access.
313+
// Smallest max_connect_time == earliest connect start == the session
314+
// closest to the connect_timeout_server_max abort.
315+
if (mct < oldest_mct) {
316+
oldest_mct = mct;
317+
oldest_idx = idx;
318+
}
305319
++idx;
306320
} else {
307321
--idle_begin;
@@ -313,6 +327,16 @@ void Base_Thread::ProcessAllSessions_Partition() {
313327
// do NOT advance idx - re-examine the swapped-in element test
314328
}
315329
}
330+
331+
// Promote the longest-waiting B session (smallest max_connect_time) to
332+
// running_end so the CONNECTING_SERVER pass serves it first. Gated by a
333+
// minimum B-band size to avoid churn on tiny bands.
334+
if (idle_begin > running_end + PARTITION_FAIRNESS_MIN_B
335+
&& oldest_idx != SIZE_MAX && oldest_idx != running_end) {
336+
void* p = mysql_sessions->pdata[running_end];
337+
mysql_sessions->pdata[running_end] = mysql_sessions->pdata[oldest_idx];
338+
mysql_sessions->pdata[oldest_idx] = p;
339+
}
316340
}
317341

318342
// this function was inline in MySQL_Thread::run()

0 commit comments

Comments
 (0)