I'm seeing a query getting stuck in the process list for long period of times with the Status of "Sending data". What does this status mean?
If someone knows more, please do fill in the gaps.
TL;DR "Sending data" seems to mean we are sending data about the query to the function that gathers that information together. It is NOT sending data to the MySQL or MariaDB client. This probably has something to do with the assembly of a JOIN command.
Finding very little good clarification on the Internet, I started looking through the MariaDB 10.2 code for "Sending Data" (yea, open source). Take all this with a some caution as I am not a C++ hacker.
You can find that in Line 10155 of sql/mysqld.cc where it is associated with
stage_sending_data. This is found in sql_select.cc Line 3561 where it is at the end of the JOIN::exec_inner function. This function is called from the function JOIN::exec(). JOIN::exec is called from the function mysql_select(). This is called from handle_select(). It appears that "Sending data" should only show up on queries with JOINs.
I think I see mysql_select() set the status "Init" or stage_init. Then "Executing" or stage_executing in JOIN::exec_inner() while it does some checks for various things that I assume break JOINs or take special attention.
Then it sets that status to "Sending data" or stage_sending_data. In the next few lines after this status is set, it runs
do_select(this, procedure);. At this point it appears to actually start gathering the information needed to provide an answer to the query. Contrary to my expectations, it is pretty clear that "Sending data" is not sending data to the client (over the network or otherwise), but to another function. It isn't yet ready to give a response. do_select() proceeds to do things like sorting temporary tables, evaluating conditions on HAVING, WHERE and stuff. It also removes locks. All that is after "Sending data" status is set.
It might be the last Status setting before actually returning the data. I haven't dug enough to state that clearly. A lot happens in do_select() so I expect the status could get changed in there somewhere, but it probably is dependent on various factors. At the end of mysql_select it does set the status to "end" or stage_end.