Open everpcpc opened 7 years ago
Thank you for the analysis: it seems pretty correct!
I think the whole idea behind enforce_autocommit_on_reads
has several limitations, like he one you just hit.
Some possible workaround are:
set sort_buffer_size
, maybe you should disable itset sort_buffer_size
into SET @@sort_buffer_size
: this will disable multiplexing (not sure if you want this)mysql-init_connect
in proxysqlA generic solution is not that trivial. What solution would work for you? How would you like ProxySQL to handle this situation?
cc @MOON-CLJ maybe we could try solution 2 first to see if #989 is resolved ?
@everpcpc okay, we can try it。
Removing set sort_buffer_size
is in my opinion the best approach right now, as disabling multiplexing for just that reason is perhaps too much.
@renecannao yes, agree. we are just debugging #989
We are about to remove set sort_buffer_size
once we can draw a conclusion with #989.
Beside, I think perhaps any statements starts with set
, not only set sort_buffer_size
or what defined in ProcessQueryAndSetStatusFlags
, should be treated as user defined variables by default for safety. It's better to disable multiplexing rather than putting a connection with problem into the connection pool.
We are about to remove set sort_buffer_size once we can draw a conclusion with #989.
Please let me know.
Beside, I think perhaps any statements starts with set, not only set sort_buffer_size or what defined in ProcessQueryAndSetStatusFlags, should be treated as user defined variables by default for safety. It's better to disable multiplexing rather than putting a connection with problem into the connection pool.
Putting a connection with problem in the connection pool is bad: I full agree with this.
Disable multiplexing for every SET
command is in some case like not having multiplexing at all.
In fact, there are a lot of drivers that run set sort_buffer_size
or set max_allowed_packet
immediately after connecting: if you use such drivers, disabling multiplexing for every SET
command will mean that multiplexing is always disabled.
If you want to disable multiplexing completely, you could set global variable mysql-multiplexing=false
.
In my opinion, what is needed is the ability to be selective choose when multiplexing should be disabled, and how to handle such cases.
Issue #1045 can be a solution.
Issue #594 can be a solution too , as mysql_query_rules
.multiplex
can now handle cases when mulltiplex needs to be disabled.
There are a lot of exceptions and corner cases, therefore I really appreciate all the reports so to be able to handle these cases correctly too.
Thanks
@renecannao
thx let me explain our problem, we provide a table router like python library for other developer in our company,we can remove "set sort_buffer_size" in our library,but we dont have full control for other developer's code,#1045 can be a solution,but it put such overhead to every query。
so my opinion,safety is more important,disabling multiplexing can be warning by log or discovered by metrics。
What directly causing this trouble is that proxysql set autocommit=false
for a special statement which backend dose not start a transaction.
So I'm thinking about, if handler_again___verify_backend_autocommit
can handle, or just skip those statements, then autocommit
will be right.
Although there are other problems still existing with those special statements.
This may be a much smaller change.
@MOON-CLJ : I agree that creating rules for every query can be an overhead. On the other hands, filtering queries can reduce network round trip, so maybe the end result is performance gain and not performance lost.
@everpcpc : I didn't understand what you mean, sorry. Can you please clarify.
@renecannao
On the other hands, filtering queries can reduce network round trip, so maybe the end result is performance gain and not performance lost.
but in this situation, most of queries will not be filtered,just very very little "set .." will be filtered。
The problem we have here is:
set sort_buffer_size=20000
comes with enforce_autocommit_on_reads=false
;is_select_NOT_for_update() == false
-> proxysql forced change backend's autocommit to false;(mysql_thread___multiplexing && (myds->myconn->reusable==true) && myds->myconn->IsActiveTransaction()==false && myds->myconn->MultiplexDisabled()==false) == true
-> proxysql push the connection with autocommit==false
to pool;select
statement comes, getting that connection with autocommit==false
while not changing it. (not expected)We can either keep the autocommit
unchanged (step2), or let the client keep this connection (step3) to handle this case.
@MOON-CLJ : that's true. but it is also true that the overhead needs to be measured. If implementing #1045 adds an overhead of 10% , is this acceptable? surely no! An overhead of 0.1% : surely acceptable! So it needs to be measured.
@everpcpc : I think I am missing something. A connection in the connection pool with autocommit=false
should not be considered a problem if there is no transaction. Does it make sense?
But when we set enforce_autocommit_on_reads=false
, we are expecting that a select
statement should not start a transaction. However, It always dose in this case if a set xxx
comes before. Looking like multiplexing is disabled.
That is right, it always starts a transaction while in reality shouldn't.
I think this should be handled by enhancing #955 (not implemented yet), defining that a hostgroup should always have autocommit enabled.
Do you still have autocommit=OFF
in the database server, as reported in #873 ?
If the database servers has autocommit=OFF
things become even more complicated.
Then maybe it would be better with an option like enforce_autocommit_true_on_reads
to ensure autocommit=true
for a select not for update
?
defining that a hostgroup should always have autocommit enabled
requires read/write splitting, which is not that easy to do and has some other problems.
Besides, we do not use autocommit=OFF
, #873 is just for testing.
This sounds a like a reasonable feature request to fix this specific problem!
^_^ many thanks~
enforce_autocommit_true_on_reads
: once implemented, this variable should be evaluated only if a transaction is not started yet
Issue #1045 is solved and available in future release 1.4.1
If I have a
set sort_buffer_size=20000
or some other set statement other than what inlib/mysql_connection.cpp#L1499
,user_variable
is not set. But however, theis_select_NOT_for_update
will be false then, making proxysql changing autocommit to false in the backend connection. Next, this connection will be put back to connection pool because mysql dose not treat this statement as a transaction. Therefore, we have a connection withautocommit=false
in the connection pool.Here the problem comes: If I have
enforce_autocommit_on_reads=false
, the autocommit will not be changed. The nextselect
statement will start a transaction which is not expected.Actually, this always happens if I make a connection with an initial statement of
set sort_buffer_size=20000
;Maybe related to https://github.com/sysown/proxysql/issues/989 ?