]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Imrpove MySQL/MariaDB dialect initialization.
authorFederico Caselli <cfederico87@gmail.com>
Thu, 30 Dec 2021 22:29:55 +0000 (23:29 +0100)
committerFederico Caselli <cfederico87@gmail.com>
Mon, 3 Jan 2022 20:41:33 +0000 (21:41 +0100)
Replace ``SHOW VARIABLES LIKE`` statement with equivalent
``SELECT @@variable`` in MySQL and MariaDB dialect initialization.
This should avoid mutex contention caused by ``SHOW VARIABLES``,
improving initialization performance.

Change-Id: Id836ef534fcc1473c7aaf9270d08a4da9b8f62cf
closes: #7518

doc/build/changelog/unreleased_14/7518.rst [new file with mode: 0644]
lib/sqlalchemy/dialects/mysql/base.py
lib/sqlalchemy/dialects/mysql/pyodbc.py
test/dialect/mysql/test_dialect.py

diff --git a/doc/build/changelog/unreleased_14/7518.rst b/doc/build/changelog/unreleased_14/7518.rst
new file mode 100644 (file)
index 0000000..6264297
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: change, mysql
+    :tickets: 7518
+
+    Replace ``SHOW VARIABLES LIKE`` statement with equivalent
+    ``SELECT @@variable`` in MySQL and MariaDB dialect initialization.
+    This should avoid mutex contention caused by ``SHOW VARIABLES``,
+    improving initialization performance.
index 5be05749549468767d63976ba9c6033693cc8d63..f20b9b6931e8ac43e65566ce0f72a9ba7f1d2725 100644 (file)
@@ -3079,24 +3079,21 @@ class MySQLDialect(default.DefaultDialect):
         # https://dev.mysql.com/doc/refman/en/identifier-case-sensitivity.html
 
         charset = self._connection_charset
-        show_var = connection.execute(
-            sql.text("SHOW VARIABLES LIKE 'lower_case_table_names'")
-        )
-        row = self._compat_first(
-            show_var,
-            charset=charset,
+        show_var = connection.exec_driver_sql(
+            "SELECT @@lower_case_table_names"
         )
+        row = self._compat_first(show_var, charset=charset)
         if not row:
             cs = 0
         else:
             # 4.0.15 returns OFF or ON according to [ticket:489]
             # 3.23 doesn't, 4.0.27 doesn't..
-            if row[1] == "OFF":
+            if row[0] == "OFF":
                 cs = 0
-            elif row[1] == "ON":
+            elif row[0] == "ON":
                 cs = 1
             else:
-                cs = int(row[1])
+                cs = int(row[0])
         self._casing = cs
         return cs
 
@@ -3115,7 +3112,7 @@ class MySQLDialect(default.DefaultDialect):
 
     def _detect_sql_mode(self, connection):
         row = self._compat_first(
-            connection.exec_driver_sql("SHOW VARIABLES LIKE 'sql_mode'"),
+            connection.exec_driver_sql("SELECT @@sql_mode"),
             charset=self._connection_charset,
         )
 
@@ -3126,7 +3123,7 @@ class MySQLDialect(default.DefaultDialect):
             )
             self._sql_mode = ""
         else:
-            self._sql_mode = row[1] or ""
+            self._sql_mode = row[0] or ""
 
     def _detect_ansiquotes(self, connection):
         """Detect and adjust for the ANSI_QUOTES sql mode."""
index 69cc6487d15ca056f779a5f9d41a52b23ec20b26..9cae7b714523299638c1ed1632274482a0587ee3 100644 (file)
@@ -43,11 +43,11 @@ Pass through exact pyodbc connection string::
 """  # noqa
 
 import re
-import sys
 
 from .base import MySQLDialect
 from .base import MySQLExecutionContext
 from .types import TIME
+from ... import exc
 from ... import util
 from ...connectors.pyodbc import PyODBCConnector
 from ...sql.sqltypes import Time
@@ -88,13 +88,14 @@ class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect):
         #
         # If it's decided that issuing that sort of SQL leaves you SOL, then
         # this can prefer the driver value.
-        rs = connection.exec_driver_sql(
-            "SHOW VARIABLES LIKE 'character_set%%'"
-        )
-        opts = {row[0]: row[1] for row in self._compat_fetchall(rs)}
-        for key in ("character_set_connection", "character_set"):
-            if opts.get(key, None):
-                return opts[key]
+        try:
+            value = connection.exec_driver_sql(
+                "select @@character_set_client"
+            ).scalar()
+            if value:
+                return value
+        except exc.DBAPIError:
+            pass
 
         util.warn(
             "Could not detect the connection character set.  "
@@ -121,15 +122,9 @@ class MySQLDialect_pyodbc(PyODBCConnector, MySQLDialect):
             #   https://github.com/mkleehammer/pyodbc/wiki/Unicode
             pyodbc_SQL_CHAR = 1  # pyodbc.SQL_CHAR
             pyodbc_SQL_WCHAR = -8  # pyodbc.SQL_WCHAR
-            if sys.version_info.major > 2:
-                conn.setdecoding(pyodbc_SQL_CHAR, encoding="utf-8")
-                conn.setdecoding(pyodbc_SQL_WCHAR, encoding="utf-8")
-                conn.setencoding(encoding="utf-8")
-            else:
-                conn.setdecoding(pyodbc_SQL_CHAR, encoding="utf-8")
-                conn.setdecoding(pyodbc_SQL_WCHAR, encoding="utf-8")
-                conn.setencoding(str, encoding="utf-8")
-                conn.setencoding(unicode, encoding="utf-8")  # noqa: F821
+            conn.setdecoding(pyodbc_SQL_CHAR, encoding="utf-8")
+            conn.setdecoding(pyodbc_SQL_WCHAR, encoding="utf-8")
+            conn.setencoding(encoding="utf-8")
 
         return on_connect
 
index 9a0f2bc0dfb9e69bc4aa5d79f722d281430a8f85..a96ea8cb489c0511e798c154f49ace2feddad344 100644 (file)
@@ -59,7 +59,7 @@ class BackendDialectTest(
         engine = engines.testing_engine()
 
         def my_execute(self, statement, *args, **kw):
-            if statement.startswith("SHOW VARIABLES"):
+            if statement.startswith("SELECT @@"):
                 statement = "SELECT 1 FROM DUAL WHERE 1=0"
             return real_exec(self, statement, *args, **kw)