Skip to content

Commit 0513a4a

Browse files
committed
MDEV-38019 Send ok packet to client earlier
Send ok packet earlier for SELECT queries that does not have any updates. This is done in select_send::send_eof() Axel's select benchmarks shows that this has a notable speed improvement: 1 Thread: 28% TPS speedup 8 Threads: 23% 64 Threads 6% This was meassured with t_oltp_point_select With InnoDB running the client over sockets. Other things: - Moved error reporting of LIMIT ROWS EXAMINED from handle_select() to check_limit_rows_examined(). This is to ensure that the error is reported before send_eof() is called. - Removed duplicate "Query execution was interrupted" messages for the same query. killed_for_exceeding_limit_rows_warning_given was introduced for this purpose. We cannot use 'killed' flag in killed_for_exceeding_limit_rows() to detect if we already have produced a warning as the 'killed' in this case is reset for each union. Reviewer: Sergei Golubchik <serg@mariadb.org>
1 parent 366de0a commit 0513a4a

8 files changed

Lines changed: 123 additions & 88 deletions

File tree

mysql-test/main/limit_rows_examined.result

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -773,7 +773,6 @@ LIMIT ROWS EXAMINED 124;
773773
field1 field2 field3 field4 field5
774774
Warnings:
775775
Warning 1931 Query execution was interrupted. The query exceeded LIMIT ROWS EXAMINED 124. The query result may be incomplete
776-
Warning 1931 Query execution was interrupted. The query exceeded LIMIT ROWS EXAMINED 124. The query result may be incomplete
777776
SHOW STATUS LIKE 'Handler_read%';
778777
Variable_name Value
779778
Handler_read_first 1

mysql-test/suite/perfschema/r/nesting.result

Lines changed: 63 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -125,15 +125,15 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re
125125
8 8 stage/sql/After opening tables (stage) STATEMENT 0
126126
9 9 stage/sql/init (stage) STATEMENT 0
127127
10 10 stage/sql/Optimizing (stage) STATEMENT 0
128-
11 11 stage/sql/Executing (stage) STATEMENT 0
129-
12 12 stage/sql/End of update loop (stage) STATEMENT 0
130-
13 14 stage/sql/Query end (stage) STATEMENT 0
131-
14 14 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 13
132-
15 15 stage/sql/closing tables (stage) STATEMENT 0
133-
16 16 stage/sql/Query end (stage) STATEMENT 0
134-
17 17 stage/sql/Starting cleanup (stage) STATEMENT 0
135-
18 18 stage/sql/Freeing items (stage) STATEMENT 0
136-
19 19 wait/io/socket/sql/client_connection send STATEMENT 0
128+
11 12 stage/sql/Executing (stage) STATEMENT 0
129+
12 12 wait/io/socket/sql/client_connection send STAGE 11
130+
13 13 stage/sql/End of update loop (stage) STATEMENT 0
131+
14 15 stage/sql/Query end (stage) STATEMENT 0
132+
15 15 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 14
133+
16 16 stage/sql/closing tables (stage) STATEMENT 0
134+
17 17 stage/sql/Query end (stage) STATEMENT 0
135+
18 18 stage/sql/Starting cleanup (stage) STATEMENT 0
136+
19 19 stage/sql/Freeing items (stage) STATEMENT 0
137137
20 21 stage/sql/Reset for next command (stage) STATEMENT 0
138138
21 21 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 20
139139
22 22 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 0
@@ -149,15 +149,15 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re
149149
32 32 stage/sql/After opening tables (stage) STATEMENT 24
150150
33 33 stage/sql/init (stage) STATEMENT 24
151151
34 34 stage/sql/Optimizing (stage) STATEMENT 24
152-
35 35 stage/sql/Executing (stage) STATEMENT 24
153-
36 36 stage/sql/End of update loop (stage) STATEMENT 24
154-
37 38 stage/sql/Query end (stage) STATEMENT 24
155-
38 38 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 37
156-
39 39 stage/sql/closing tables (stage) STATEMENT 24
157-
40 40 stage/sql/Query end (stage) STATEMENT 24
158-
41 41 stage/sql/Starting cleanup (stage) STATEMENT 24
159-
42 42 stage/sql/Freeing items (stage) STATEMENT 24
160-
43 43 wait/io/socket/sql/client_connection send STATEMENT 24
152+
35 36 stage/sql/Executing (stage) STATEMENT 24
153+
36 36 wait/io/socket/sql/client_connection send STAGE 35
154+
37 37 stage/sql/End of update loop (stage) STATEMENT 24
155+
38 39 stage/sql/Query end (stage) STATEMENT 24
156+
39 39 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 38
157+
40 40 stage/sql/closing tables (stage) STATEMENT 24
158+
41 41 stage/sql/Query end (stage) STATEMENT 24
159+
42 42 stage/sql/Starting cleanup (stage) STATEMENT 24
160+
43 43 stage/sql/Freeing items (stage) STATEMENT 24
161161
44 45 stage/sql/Reset for next command (stage) STATEMENT 24
162162
45 45 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 44
163163
46 46 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 24
@@ -173,15 +173,15 @@ relative_event_id relative_end_event_id event_name comment nesting_event_type re
173173
56 56 stage/sql/After opening tables (stage) STATEMENT 48
174174
57 57 stage/sql/init (stage) STATEMENT 48
175175
58 58 stage/sql/Optimizing (stage) STATEMENT 48
176-
59 59 stage/sql/Executing (stage) STATEMENT 48
177-
60 60 stage/sql/End of update loop (stage) STATEMENT 48
178-
61 62 stage/sql/Query end (stage) STATEMENT 48
179-
62 62 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 61
180-
63 63 stage/sql/closing tables (stage) STATEMENT 48
181-
64 64 stage/sql/Query end (stage) STATEMENT 48
182-
65 65 stage/sql/Starting cleanup (stage) STATEMENT 48
183-
66 66 stage/sql/Freeing items (stage) STATEMENT 48
184-
67 67 wait/io/socket/sql/client_connection send STATEMENT 48
176+
59 60 stage/sql/Executing (stage) STATEMENT 48
177+
60 60 wait/io/socket/sql/client_connection send STAGE 59
178+
61 61 stage/sql/End of update loop (stage) STATEMENT 48
179+
62 63 stage/sql/Query end (stage) STATEMENT 48
180+
63 63 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 62
181+
64 64 stage/sql/closing tables (stage) STATEMENT 48
182+
65 65 stage/sql/Query end (stage) STATEMENT 48
183+
66 66 stage/sql/Starting cleanup (stage) STATEMENT 48
184+
67 67 stage/sql/Freeing items (stage) STATEMENT 48
185185
68 69 stage/sql/Reset for next command (stage) STATEMENT 48
186186
69 69 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 68
187187
70 70 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 48
@@ -200,15 +200,15 @@ select "With a third part to make things complete" as payload NULL NULL
200200
81 81 stage/sql/After opening tables (stage) STATEMENT 72
201201
82 82 stage/sql/init (stage) STATEMENT 72
202202
83 83 stage/sql/Optimizing (stage) STATEMENT 72
203-
84 84 stage/sql/Executing (stage) STATEMENT 72
204-
85 85 stage/sql/End of update loop (stage) STATEMENT 72
205-
86 87 stage/sql/Query end (stage) STATEMENT 72
206-
87 87 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 86
207-
88 88 stage/sql/closing tables (stage) STATEMENT 72
208-
89 89 stage/sql/Query end (stage) STATEMENT 72
209-
90 90 stage/sql/Starting cleanup (stage) STATEMENT 72
210-
91 92 stage/sql/Freeing items (stage) STATEMENT 72
211-
92 92 wait/io/socket/sql/client_connection send STAGE 91
203+
84 85 stage/sql/Executing (stage) STATEMENT 72
204+
85 85 wait/io/socket/sql/client_connection send STAGE 84
205+
86 86 stage/sql/End of update loop (stage) STATEMENT 72
206+
87 88 stage/sql/Query end (stage) STATEMENT 72
207+
88 88 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 87
208+
89 89 stage/sql/closing tables (stage) STATEMENT 72
209+
90 90 stage/sql/Query end (stage) STATEMENT 72
210+
91 91 stage/sql/Starting cleanup (stage) STATEMENT 72
211+
92 92 stage/sql/Freeing items (stage) STATEMENT 72
212212
93 110 statement/sql/select select "And this is the second part of a multi query" as payload;
213213
select "With a third part to make things complete" as payload NULL NULL
214214
94 96 stage/sql/starting (stage) STATEMENT 93
@@ -219,15 +219,15 @@ select "With a third part to make things complete" as payload NULL NULL
219219
99 99 stage/sql/After opening tables (stage) STATEMENT 93
220220
100 100 stage/sql/init (stage) STATEMENT 93
221221
101 101 stage/sql/Optimizing (stage) STATEMENT 93
222-
102 102 stage/sql/Executing (stage) STATEMENT 93
223-
103 103 stage/sql/End of update loop (stage) STATEMENT 93
224-
104 105 stage/sql/Query end (stage) STATEMENT 93
225-
105 105 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 104
226-
106 106 stage/sql/closing tables (stage) STATEMENT 93
227-
107 107 stage/sql/Query end (stage) STATEMENT 93
228-
108 108 stage/sql/Starting cleanup (stage) STATEMENT 93
229-
109 110 stage/sql/Freeing items (stage) STATEMENT 93
230-
110 110 wait/io/socket/sql/client_connection send STAGE 109
222+
102 103 stage/sql/Executing (stage) STATEMENT 93
223+
103 103 wait/io/socket/sql/client_connection send STAGE 102
224+
104 104 stage/sql/End of update loop (stage) STATEMENT 93
225+
105 106 stage/sql/Query end (stage) STATEMENT 93
226+
106 106 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 105
227+
107 107 stage/sql/closing tables (stage) STATEMENT 93
228+
108 108 stage/sql/Query end (stage) STATEMENT 93
229+
109 109 stage/sql/Starting cleanup (stage) STATEMENT 93
230+
110 110 stage/sql/Freeing items (stage) STATEMENT 93
231231
111 129 statement/sql/select select "With a third part to make things complete" as payload NULL NULL
232232
112 113 stage/sql/starting (stage) STATEMENT 111
233233
113 113 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 112
@@ -236,15 +236,15 @@ select "With a third part to make things complete" as payload NULL NULL
236236
116 116 stage/sql/After opening tables (stage) STATEMENT 111
237237
117 117 stage/sql/init (stage) STATEMENT 111
238238
118 118 stage/sql/Optimizing (stage) STATEMENT 111
239-
119 119 stage/sql/Executing (stage) STATEMENT 111
240-
120 120 stage/sql/End of update loop (stage) STATEMENT 111
241-
121 122 stage/sql/Query end (stage) STATEMENT 111
242-
122 122 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 121
243-
123 123 stage/sql/closing tables (stage) STATEMENT 111
244-
124 124 stage/sql/Query end (stage) STATEMENT 111
245-
125 125 stage/sql/Starting cleanup (stage) STATEMENT 111
246-
126 126 stage/sql/Freeing items (stage) STATEMENT 111
247-
127 127 wait/io/socket/sql/client_connection send STATEMENT 111
239+
119 120 stage/sql/Executing (stage) STATEMENT 111
240+
120 120 wait/io/socket/sql/client_connection send STAGE 119
241+
121 121 stage/sql/End of update loop (stage) STATEMENT 111
242+
122 123 stage/sql/Query end (stage) STATEMENT 111
243+
123 123 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 122
244+
124 124 stage/sql/closing tables (stage) STATEMENT 111
245+
125 125 stage/sql/Query end (stage) STATEMENT 111
246+
126 126 stage/sql/Starting cleanup (stage) STATEMENT 111
247+
127 127 stage/sql/Freeing items (stage) STATEMENT 111
248248
128 129 stage/sql/Reset for next command (stage) STATEMENT 111
249249
129 129 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 128
250250
130 130 wait/synch/mutex/sql/THD::LOCK_thd_data lock STATEMENT 111
@@ -260,15 +260,15 @@ select "With a third part to make things complete" as payload NULL NULL
260260
140 140 stage/sql/After opening tables (stage) STATEMENT 132
261261
141 141 stage/sql/init (stage) STATEMENT 132
262262
142 142 stage/sql/Optimizing (stage) STATEMENT 132
263-
143 143 stage/sql/Executing (stage) STATEMENT 132
264-
144 144 stage/sql/End of update loop (stage) STATEMENT 132
265-
145 146 stage/sql/Query end (stage) STATEMENT 132
266-
146 146 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 145
267-
147 147 stage/sql/closing tables (stage) STATEMENT 132
268-
148 148 stage/sql/Query end (stage) STATEMENT 132
269-
149 149 stage/sql/Starting cleanup (stage) STATEMENT 132
270-
150 150 stage/sql/Freeing items (stage) STATEMENT 132
271-
151 151 wait/io/socket/sql/client_connection send STATEMENT 132
263+
143 144 stage/sql/Executing (stage) STATEMENT 132
264+
144 144 wait/io/socket/sql/client_connection send STAGE 143
265+
145 145 stage/sql/End of update loop (stage) STATEMENT 132
266+
146 147 stage/sql/Query end (stage) STATEMENT 132
267+
147 147 wait/synch/mutex/sql/THD::LOCK_thd_kill lock STAGE 146
268+
148 148 stage/sql/closing tables (stage) STATEMENT 132
269+
149 149 stage/sql/Query end (stage) STATEMENT 132
270+
150 150 stage/sql/Starting cleanup (stage) STATEMENT 132
271+
151 151 stage/sql/Freeing items (stage) STATEMENT 132
272272
152 153 stage/sql/Reset for next command (stage) STATEMENT 132
273273
153 153 wait/synch/mutex/sql/THD::LOCK_thd_data lock STAGE 152
274274
disconnect con1;

sql/protocol.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -580,10 +580,9 @@ void Protocol::end_statement()
580580
#endif /* WITH_WSREP */
581581

582582
DBUG_ENTER("Protocol::end_statement");
583-
DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
584583
bool error= FALSE;
585584

586-
/* Can not be true, but do not take chances in production. */
585+
/* This can set in the case of early result sent by select_send::send_eof() */
587586
if (thd->get_stmt_da()->is_sent())
588587
DBUG_VOID_RETURN;
589588

sql/sql_class.cc

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,6 +884,7 @@ THD::THD(my_thread_id id, bool is_wsrep_applier)
884884
net.reading_or_writing= 0;
885885
client_capabilities= 0; // minimalistic client
886886
system_thread= NON_SYSTEM_THREAD;
887+
killed_for_exceeding_limit_rows_warning_given= 0;
887888
shared_thd= 0;
888889
cleanup_done= free_connection_done= abort_on_warning= got_warning= 0;
889890
peer_port= 0; // For SHOW PROCESSLIST
@@ -2358,6 +2359,32 @@ void THD::reset_killed()
23582359
DBUG_VOID_RETURN;
23592360
}
23602361

2362+
2363+
/*
2364+
Mark query killed for exceeding limit rows
2365+
2366+
The current select will be aborted, but the incomplete result set will
2367+
be sent to the user
2368+
*/
2369+
2370+
void THD::killed_for_exceeding_limit_rows()
2371+
{
2372+
set_killed(ABORT_QUERY);
2373+
if (!no_errors && !killed_for_exceeding_limit_rows_warning_given)
2374+
{
2375+
killed_for_exceeding_limit_rows_warning_given= 1;
2376+
bool saved_abort_on_warning= abort_on_warning;
2377+
abort_on_warning= false;
2378+
push_warning_printf(this, Sql_condition::WARN_LEVEL_WARN,
2379+
ER_QUERY_RESULT_INCOMPLETE,
2380+
ER_THD(this, ER_QUERY_RESULT_INCOMPLETE),
2381+
"LIMIT ROWS EXAMINED",
2382+
lex->limit_rows_examined->val_uint());
2383+
abort_on_warning= saved_abort_on_warning;
2384+
}
2385+
}
2386+
2387+
23612388
/*
23622389
Remember the location of thread info, the structure needed for
23632390
the structure for the net buffer
@@ -3371,13 +3398,34 @@ int select_send::send_data(List<Item> &items)
33713398

33723399
bool select_send::send_eof()
33733400
{
3374-
/*
3401+
/*
33753402
Don't send EOF if we're in error condition (which implies we've already
33763403
sent or are sending an error)
33773404
*/
33783405
if (unlikely(thd->is_error()))
3406+
{
3407+
reset_for_next_ps_execution();
33793408
return TRUE;
3409+
}
3410+
33803411
::my_eof(thd);
3412+
3413+
if (unlikely(thd->lex->sql_command != SQLCOM_SELECT))
3414+
goto end; // For DELETE RETURNING
3415+
3416+
if (likely(!thd->transaction->stmt.is_trx_read_write()))
3417+
{
3418+
/*
3419+
We are executing a readonly statement. Send the result to the
3420+
client so that it can process the data while the server is doing
3421+
cleanups.
3422+
*/
3423+
thd->push_final_warnings();
3424+
thd->update_server_status(); // Needed for slow query status
3425+
thd->protocol->end_statement();
3426+
}
3427+
3428+
end:
33813429
reset_for_next_ps_execution();
33823430
return FALSE;
33833431
}
@@ -4679,7 +4727,6 @@ bool select_dumpvar::send_eof()
46794727
}
46804728

46814729

4682-
46834730
bool
46844731
select_materialize_with_stats::
46854732
create_result_table(THD *thd_arg, List<Item> *column_types,

sql/sql_class.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3403,6 +3403,7 @@ class THD: public THD_count, /* this must be first */
34033403
must be reset (all items be removed from it).
34043404
*/
34053405
bool reset_sp_cache;
3406+
bool killed_for_exceeding_limit_rows_warning_given;
34063407

34073408
/* container for handler's private per-connection data */
34083409
Ha_data ha_data[MAX_HA];
@@ -4010,10 +4011,11 @@ class THD: public THD_count, /* this must be first */
40104011
Check if the number of rows accessed by a statement exceeded
40114012
LIMIT ROWS EXAMINED. If so, signal the query engine to stop execution.
40124013
*/
4014+
void killed_for_exceeding_limit_rows();
40134015
inline void check_limit_rows_examined()
40144016
{
40154017
if (++accessed_rows_and_keys > lex->limit_rows_examined_cnt)
4016-
set_killed(ABORT_QUERY);
4018+
killed_for_exceeding_limit_rows();
40174019
}
40184020

40194021
USER_CONN *user_connect;

sql/sql_select.cc

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -655,21 +655,16 @@ bool handle_select(THD *thd, LEX *lex, select_result *result,
655655
if (unlikely(thd->killed == ABORT_QUERY && !thd->no_errors))
656656
{
657657
/*
658-
If LIMIT ROWS EXAMINED interrupted query execution, issue a warning,
659-
continue with normal processing and produce an incomplete query result.
658+
If LIMIT ROWS EXAMINED interrupted query execution
659+
continue with normal processing and produce an incomplete query
660+
result.
661+
A warning was generated by killed_for_exceeding_limit_rows().
660662
*/
661-
bool saved_abort_on_warning= thd->abort_on_warning;
662-
thd->abort_on_warning= false;
663-
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
664-
ER_QUERY_RESULT_INCOMPLETE,
665-
ER_THD(thd, ER_QUERY_RESULT_INCOMPLETE),
666-
"LIMIT ROWS EXAMINED",
667-
thd->lex->limit_rows_examined->val_uint());
668-
thd->abort_on_warning= saved_abort_on_warning;
669663
thd->reset_killed();
670664
}
671665
/* Deactivate LIMIT ROWS EXAMINED after query execution. */
672666
thd->lex->deactivate_limit_rows_examined();
667+
thd->killed_for_exceeding_limit_rows_warning_given= 0;
673668

674669
MYSQL_SELECT_DONE((int) res, (ulong) thd->limit_found_rows);
675670
DBUG_RETURN(res);

sql/sql_union.cc

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,11 +2518,6 @@ bool st_select_lex_unit::exec_inner()
25182518
Stop execution of the remaining queries in the UNIONS, and produce
25192519
the current result.
25202520
*/
2521-
push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
2522-
ER_QUERY_RESULT_INCOMPLETE,
2523-
ER_THD(thd, ER_QUERY_RESULT_INCOMPLETE),
2524-
"LIMIT ROWS EXAMINED",
2525-
thd->lex->limit_rows_examined->val_uint());
25262521
thd->reset_killed();
25272522
break;
25282523
}

storage/maria/ha_maria.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3013,11 +3013,9 @@ int ha_maria::external_lock(THD *thd, int lock_type)
30133013
!trnman_decrement_locked_tables(trn))
30143014
{
30153015
/*
3016-
OK should not have been sent to client yet (ACID).
3017-
This is a bit excessive, ACID requires this only if there are some
3018-
changes to commit (rollback shouldn't be tested).
3016+
OK should not have been sent to client in case of write (ACID).
30193017
*/
3020-
DBUG_ASSERT(!thd->get_stmt_da()->is_sent() ||
3018+
DBUG_ASSERT(!trn->undo_lsn || !thd->get_stmt_da()->is_sent() ||
30213019
thd->killed);
30223020
/*
30233021
If autocommit, commit transaction. This can happen when open and

0 commit comments

Comments
 (0)