Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(mysql): be explicit that batch queries are parameterless #10095

Merged
merged 6 commits into from Mar 14, 2023

Conversation

keynslug
Copy link
Contributor

@keynslug keynslug commented Mar 8, 2023

So that mysql client won't attempt to prepare them automatically, thus trashing the server's prepared statements table and making whole interaction overall heavier. Also add tests to verify that we don't allocate more prepared statements than needed.

This PR also fixes an issue where some strings might have been inserted inconsistently, since escaping logic missed some edge cases.


EEC-782
EMQX-9167

@keynslug keynslug requested review from a team, lafirest and JimMoen as code owners March 8, 2023 14:48
@keynslug keynslug force-pushed the fix/EEC-782/mysql-prepstmt-exhaustion branch 2 times, most recently from ab7841d to db2cfbc Compare March 8, 2023 18:05
@@ -160,7 +160,7 @@ status_result(_Status = false) -> connecting.
%%========================================================================================

do_batch_insert(InstanceId, BatchReqs, InsertPart, Tokens, State) ->
SQL = emqx_plugin_libs_rule:proc_batch_sql(BatchReqs, InsertPart, Tokens),
SQL = emqx_plugin_libs_rule:proc_batch_mysql(BatchReqs, InsertPart, Tokens),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: since this is also used in TDengine, maybe the function name could be something more generic (perhaps the old name)?

Either this or "fork" the old function so that TDengine uses the old version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did that as part of 2544742. I tried to raise some awareness there about pgsql in a comment, would be glad if you take another look.

thalesmg
thalesmg previously approved these changes Mar 8, 2023
Copy link
Contributor

@thalesmg thalesmg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still digesting the escaping logic, but don't want to block the fix.

@@ -28,7 +28,7 @@
preproc_sql/1,
preproc_sql/2,
proc_sql/2,
proc_sql_param_str/2,
proc_mysql_param_str/2,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adding a new function with this name may be better than replacing the generic function, there are many SQL-likes backend.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did that as part of 2544742. I tried to raise some awareness there about pgsql in a comment, would be glad if you take another look.

@lafirest
Copy link
Member

lafirest commented Mar 9, 2023

@keynslug
awesome PR, could you share what happened and the reason for the performance improvement?
And a change file in English is required, I can translate it into Chinese.

@keynslug
Copy link
Contributor Author

keynslug commented Mar 9, 2023

Thanks, @lafirest.

could you share what happened and the reason for the performance improvement?

This is actually a speculation if this will improve performance, but I suspect it will, slightly, because we now won't hit whole layer of caching prepared statements in the client.

And a change file in English is required, I can translate it into Chinese.

Sure, will do shortly, along with other post-review changes.

@keynslug
Copy link
Contributor Author

keynslug commented Mar 9, 2023

could you share what happened and the reason for the performance improvement?

Replied too quickly. 😅 What I meant is that while trying to hit some hot codepath and pinpoint where does a performance regression come from, under my workload I actually observed message loss due to prepared statements table exhaustion on the server. So this PR is not actually addressing a root cause for the performance regression, but theoretically, might contribute to it.

Also hit some concerning error from the server (about SQL syntax error) that forced me to reimplement escaping logic.

@keynslug keynslug force-pushed the fix/EEC-782/mysql-prepstmt-exhaustion branch 3 times, most recently from 37d1433 to 870f820 Compare March 9, 2023 11:13
@coveralls
Copy link
Collaborator

Pull Request Test Coverage Report for Build 4373849295

  • 35 of 37 (94.59%) changed or added relevant lines in 3 files are covered.
  • 28 unchanged lines in 13 files lost coverage.
  • Overall coverage increased (+0.01%) to 80.879%

Changes Missing Coverage Covered Lines Changed/Added Lines %
apps/emqx_connector/src/emqx_connector_mysql.erl 8 9 88.89%
apps/emqx_plugin_libs/src/emqx_placeholder.erl 26 27 96.3%
Files with Coverage Reduction New Missed Lines %
apps/emqx_machine/src/emqx_machine.erl 1 80.0%
apps/emqx/src/emqx_channel.erl 1 87.42%
apps/emqx/src/emqx_config.erl 1 86.51%
apps/emqx/src/emqx_connection.erl 1 87.96%
apps/emqx/src/emqx_logger.erl 1 80.49%
apps/emqx/src/emqx_schema.erl 1 90.91%
apps/emqx/src/emqx_session.erl 1 87.2%
lib-ee/emqx_ee_connector/src/emqx_ee_connector_influxdb.erl 1 90.05%
apps/emqx_resource/src/emqx_resource_buffer_worker_sup.erl 2 86.96%
apps/emqx/src/emqx_alarm.erl 2 91.89%
Totals Coverage Status
Change from base Build 4372045048: 0.01%
Covered Lines: 24149
Relevant Lines: 29858

💛 - Coveralls

thalesmg
thalesmg previously approved these changes Mar 9, 2023
@keynslug
Copy link
Contributor Author

And a change file in English is required, I can translate it into Chinese.

Hi @lafirest, I've attached a changelog entry with DeepL-ed Chinese translation, much appreciate if you could take a quick read-through.

@@ -0,0 +1,3 @@
阻止 mysql 客户端在每个批处理中用不必要的 `PREPARE` 查询反复轰炸mysql服务器,破坏服务器并耗尽其内部限制。当 mysql 桥处于批处理模式时,这种情况正在发生。
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

优化 MySQL 桥接在批量模式下能更高效的使用预处理语句 ,减少了对 MySQL 服务器的查询压力, 并确保对 SQL 语句进行更安全和谨慎的转义。

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't translate it word for word, but the meaning is correct.

@@ -0,0 +1,3 @@
Stop mysql client from bombarding mysql server repeatedly with unnecessary `PREPARE` queries on every batch, trashing the server and exhausting its internal limits. This was happening when the mysql bridge was in the batch mode.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: mysql -> MySQL

@keynslug keynslug force-pushed the fix/EEC-782/mysql-prepstmt-exhaustion branch 3 times, most recently from 2757d46 to ac2b4a5 Compare March 10, 2023 10:23
@keynslug keynslug changed the base branch from release-50 to master March 10, 2023 10:23
Also make them look as recommended in the documentation.
So that mysql client won't attempt to prepare them automatically, thus
trashing the server's prepared statements table and making interaction
overall heavier.
Also hexencode non-utf8 binaries. This is essentially an heuristic.
We don't know column types in runtime, and there's no simple way
to find them out. Since we're already doing full binary scan during
escaping it should be cheap to bail out on non-utf8 strings and
hexencode them instead.

Also introduce separate function to highlight that this escaping
is MySQL-specific.
Bump `emqx_plugin_libs` app version to 4.3.7.
Similar to what we have in mysql and pgqsl testsuites.
@keynslug keynslug force-pushed the fix/EEC-782/mysql-prepstmt-exhaustion branch from ac2b4a5 to f7c0d29 Compare March 10, 2023 15:43
@keynslug keynslug requested a review from lafirest March 13, 2023 17:17
@keynslug keynslug merged commit a530ccb into emqx:master Mar 14, 2023
@keynslug keynslug deleted the fix/EEC-782/mysql-prepstmt-exhaustion branch March 14, 2023 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants