[MXS-3416] causal_reads=global returns an unexpected OK packet Created: 2021-02-24  Updated: 2021-03-02  Resolved: 2021-03-02

Status: Closed
Project: MariaDB MaxScale
Component/s: readwritesplit
Affects Version/s: 2.5.8
Fix Version/s: 2.5.9

Type: Bug Priority: Major
Reporter: markus makela Assignee: markus makela
Resolution: Fixed Votes: 0
Labels: None


 Description   

The OK packet returned by the MASTER_GTID_WAIT() call that causal_reads executes is not always removed.

This was reported along with a network trace and from it can be seen that the same query sometimes returns an OK packet with the more results follow flag set. Theoretically this could be a bug in the server but the simplest explanation is that under some conditions MaxScale fails to properly process the result.

I have yet to reproduce this with a similar setup and a script that repeatedly executes a query that returns a known row that has replicated to the server.



 Comments   
Comment by markus makela [ 2021-02-26 ]

I believe I have reproduced the problem with the following program:

#include <iostream>
#include <mysql.h>
 
using namespace std;
 
int main(int argc, char** argv)
{
    bool ok = true;
    int i = 0;
    int port = argc > 1 ? atoi(argv[1]) : 4006;
    MYSQL* mysql = mysql_init(NULL);
 
    cout << "Connect" << endl;
 
    if (!mysql_real_connect(mysql, "127.0.0.1", "maxuser", "maxpwd", NULL, port, NULL, 0))
    {
        cout << "Failed to connect to database: " << mysql_error(mysql) << endl;
        mysql_close(mysql);
        return 1;
    }
 
    do
    {
        ++i;
        mysql_ping(mysql);
 
        if (mysql_query(mysql, "SELECT 1 as one, 2 as two"))
        {
            cout << "SELECT failed: " << mysql_error(mysql) << endl;
            ok = false;
        }
        else
        {
            if (MYSQL_RES* result = mysql_store_result(mysql))
            {
                mysql_free_result(result);
            }
            else
            {
                cout << "No result at " << i << endl;
                ok = false;
 
                if (mysql_more_results(mysql))
                {
                    cout << "More results follow" << endl;
                }
            }
        }
    }
    while (ok);
 
    cout << "Disconnect" << endl;
    mysql_close(mysql);
 
    return 0;
}

The important part is the mysql_ping() call done right before mysql_query(). Without it the test works fine but with it, the test always failed within 1000 iterations for me.

Comment by markus makela [ 2021-02-26 ]

There is a race condition of sorts in the code that handles the causal read responses. If multiple backends delivered responses at the same time, the two would get mixed up which would cause the other to have an extra OK packet that was not expected. This can only happen with MaxScale 2.5 when a command that is routed to all servers (a session command) doesn't complete on all servers before the next query is routed.

Generated at Thu Feb 08 04:21:15 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.