Uploaded image for project: 'RHEL'
  1. RHEL
  2. RHEL-51350

Issue with python-PyMySQL and MariaDB

    • Icon: Bug Bug
    • Resolution: Unresolved
    • Icon: Minor Minor
    • None
    • rhel-9.4.z
    • mariadb-connector-c
    • No
    • Low
    • rhel-sst-cs-databases
    • None
    • False
    • Hide

      None

      Show
      None
    • None
    • Red Hat Enterprise Linux
    • None
    • None
    • None
    • Unspecified
    • None

      What were you trying to do that didn't work?

      Running a Python script that connects to a MariaDB server.

      I was first running a frappe framework application which uses python PyMySQL to connect to the DB.

      I am always getting access denied using password yes, despite the password being correct.

      Did an equivalent shell script, connects to the database successfully and executes a command - select user()

      Doesn't matter if it is system python or new python.

      I am adding a detailed description in the end. I replicated this issue on all EL9 distros I tested. 

      Please provide the package NVR for which bug is seen:

      mariadb-connector-c-3.2.6-1.el9

      How reproducible:

      Install mariadb-connector-c and try to connect to an external MariaDB Server

      Steps to reproduce

      1. Base OS with Minimal install + Development Tools
      2. Install mariadb-connector-c
      3. Install python MariaDB Connector and try to connect to an external MariaDB Server.

      Expected results

      Connection successful

      Actual results

      Fails.

      A more in-depth and detailed explanation of the issue (please read):

      This has been reproduced on:

      • RockyLinux 9
      • AlmaLinux 9
      • RHEL 9

      Initially I found the issue when installing the frappe framework on a RL9 machine. From there I have been able to easily reproduce the issue in several environments.
      Frappe uses PyMySQL lib, and on all the tests I did, the only lib that actually worked was MySQL. I'll get to that ahead.

      So I started with a minimum install base system (always), then added `dnf groupinstall 'Development Tools'`
      I initially compiled Python3.11 from sources.
      Then used Python3.11 supplied by @appstream
      I reproduce these results either from sources or from repo.
      I did an additional test using system supplied Python3.9 and the results are also reproducible. So it is not related to Python being 3.9 or 3.11.

      So I added python3.11, python3.11-pip, python3.11-devel
      After I installed the MariaDB-Connector-C and -devel from the repos.

      Running `pip3.11 install mariadb` fails with:

      # pip3.11 install mariadb
      Collecting mariadb
        Using cached mariadb-1.1.10.tar.gz (84 kB)
        Installing build dependencies ... done
        Getting requirements to build wheel ... error
        error: subprocess-exited-with-error
        
        × Getting requirements to build wheel did not run successfully.
        │ exit code: 2
        ╰─> [1 lines of output]
            MariaDB Connector/Python requires MariaDB Connector/C >= 3.3.1, found version 3.2.6
            [end of output]
        
        note: This error originates from a subprocess, and is likely not a problem with pip.
      error: subprocess-exited-with-error
      × Getting requirements to build wheel did not run successfully.
      │ exit code: 2
      ╰─> See above for output.
      note: This error originates from a subprocess, and is likely not a problem with pip.
      

      So, since the only connector provided is `3.2.6`, I tried to install a lower version of MariaDB on Python:

      # pip3.11 install mariadb==1.0.11
      Collecting mariadb==1.0.11
        Using cached mariadb-1.0.11.zip (85 kB)
        Preparing metadata (setup.py) ... done
      Installing collected packages: mariadb
        DEPRECATION: mariadb is being installed using the legacy 'setup.py install' method, because it does not have a 'pyproject.toml' and the 'wheel' package is not installed. pip 23.1 will enforce this behaviour change. A possible replacement is to enable the '--use-pep517' option. Discussion can be found at https://github.com/pypa/pip/issues/8559
        Running setup.py install for mariadb ... error
        error: subprocess-exited-with-error
        
        × Running setup.py install for mariadb did not run successfully.
        │ exit code: 1
        ╰─> [40 lines of output]
            running install
            /usr/lib/python3.11/site-packages/setuptools/command/install.py:34: SetuptoolsDeprecationWarning: setup.py install is deprecated. Use build and pip and other standards-based tools.
              warnings.warn(
            running build
            running build_py
            creating build
            creating build/lib.linux-x86_64-cpython-311
            creating build/lib.linux-x86_64-cpython-311/mariadb
            copying mariadb/__init__.py -> build/lib.linux-x86_64-cpython-311/mariadb
            creating build/lib.linux-x86_64-cpython-311/mariadb/constants
            copying mariadb/constants/__init__.py -> build/lib.linux-x86_64-cpython-311/mariadb/constants
            copying mariadb/constants/CLIENT.py -> build/lib.linux-x86_64-cpython-311/mariadb/constants
            copying mariadb/constants/INDICATOR.py -> build/lib.linux-x86_64-cpython-311/mariadb/constants
            copying mariadb/constants/CURSOR.py -> build/lib.linux-x86_64-cpython-311/mariadb/constants
            copying mariadb/constants/FIELD_TYPE.py -> build/lib.linux-x86_64-cpython-311/mariadb/constants
            running build_ext
            building 'mariadb._mariadb' extension
            creating build/temp.linux-x86_64-cpython-311
            creating build/temp.linux-x86_64-cpython-311/mariadb
            gcc -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -O2 -fexceptions -g -grecord-gcc-switches -pipe -Wall -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -m64 -march=x86-64-v2 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -D_GNU_SOURCE -fPIC -fwrapv -fPIC -DPY_MARIADB_MAJOR_VERSION=1 -DPY_MARIADB_MINOR_VERSION=0 -DPY_MARIADB_PATCH_VERSION=11 -I/usr/include/mysql -I/usr/include/mysql/mysql -I./include -I/usr/include/python3.11 -c mariadb/mariadb.c -o build/temp.linux-x86_64-cpython-311/mariadb/mariadb.o -DDEFAULT_PLUGINS_SUBDIR=\"/usr/lib64/mariadb/plugin\"
            mariadb/mariadb.c: In function 'PyInit__mariadb':
            mariadb/mariadb.c:155:35: error: lvalue required as left operand of assignment
              155 |     Py_TYPE(&MrdbConnection_Type) = &PyType_Type;
                  |                                   ^
            mariadb/mariadb.c:168:31: error: lvalue required as left operand of assignment
              168 |     Py_TYPE(&MrdbCursor_Type) = &PyType_Type;
                  |                               ^
            mariadb/mariadb.c:174:29: error: lvalue required as left operand of assignment
              174 |     Py_TYPE(&MrdbPool_Type) = &PyType_Type;
                  |                             ^
            mariadb/mariadb.c:180:34: error: lvalue required as left operand of assignment
              180 |     Py_TYPE(&MrdbIndicator_Type) = &PyType_Type;
                  |                                  ^
            mariadb/mariadb.c:186:38: error: lvalue required as left operand of assignment
              186 |     Py_TYPE(&Mariadb_Fieldinfo_Type) = &PyType_Type;
                  |                                      ^
            mariadb/mariadb.c:192:38: error: lvalue required as left operand of assignment
              192 |     Py_TYPE(&Mariadb_DBAPIType_Type) = &PyType_Type;
                  |                                      ^
            error: command '/usr/bin/gcc' failed with exit code 1
            [end of output]
        
        note: This error originates from a subprocess, and is likely not a problem with pip.
      error: legacy-install-failure
      × Encountered error while trying to install package.
      ╰─> mariadb
      note: This is an issue with the package mentioned above, not pip.
      hint: See above for output from the failure.
      

      I tried all versions down to mariadb==1.0.0. None installs successfully.

      The result is exactly the same, no matter what mariadb python3 I'm using or EL9 distro I'm using. I can reproduce this every time.

      So since mariadb-connector-c-3.2.6 doesn't make it, I went to mariadb-connector-c-3.3.10 from MariaDB website, which only provides a `tar.gz` with stuff pre-compiled? weird.
      Anyway got the source package from GitHub:
      MariaDB Corporation - MariaDB Connector C - Archive - Refs - Tags - v3.3.10

      to build:

      cd mariadb-connector-c
      cmake -S . -B build
      cd build && make
      make install

      And adding MariaDB to python:

      # pip3.11 install mariadb
      Collecting mariadb
        Using cached mariadb-1.1.10.tar.gz (84 kB)
        Installing build dependencies ... done
        Getting requirements to build wheel ... done
        Preparing metadata (pyproject.toml) ... done
      Collecting packaging
        Using cached packaging-24.1-py3-none-any.whl (53 kB)
      Building wheels for collected packages: mariadb
        Building wheel for mariadb (pyproject.toml) ... done
        Created wheel for mariadb: filename=mariadb-1.1.10-cp311-cp311-linux_x86_64.whl size=193885 sha256=d5873661130b26edc8f5a596d8a6e4f33a692cf10141e8246f1480ace82ac088
        Stored in directory: /root/.cache/pip/wheels/ad/96/e6/aa53808d09799f9d1c4f53eb127936c98d8a6bf971af53fe86
      Successfully built mariadb
      Installing collected packages: packaging, mariadb
      Successfully installed mariadb-1.1.10 packaging-24.1
      WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

       

      All good until now. So now let's test our script:

      # python3.11 mariadb-db-test.py 
      Traceback (most recent call last):
        File "/root/mariadb-db-test.py", line 2, in <module>
          import mariadb
        File "/usr/local/lib64/python3.11/site-packages/mariadb/__init__.py", line 7, in <module>
          from ._mariadb import (
      ImportError: libmariadb.so.3: cannot open shared object file: No such file or directory

       

      To correct this, add a file to`/etc/ld.so.conf.d` like `mariadb-connector-c-libs.conf` with content:

      /usr/local/lib/mariadb

      And run `ldconfig`

       

      Then running the Python Script:

      # python3.11 mariadb-db-test.py 
      Traceback (most recent call last):
        File "/root/mariadb-db-test.py", line 29, in <module>
          display_user()
        File "/root/mariadb-db-test.py", line 26, in display_user
          result = execute_query(query)
                   ^^^^^^^^^^^^^^^^^^^^
        File "/root/mariadb-db-test.py", line 10, in execute_query
          conn = mariadb.connect(
                 ^^^^^^^^^^^^^^^^
        File "/usr/local/lib64/python3.11/site-packages/mariadb/__init__.py", line 146, in connect
          connection = connectionclass(*args, **kwargs)
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        File "/usr/local/lib64/python3.11/site-packages/mariadb/connections.py", line 85, in __init__
          super().__init__(*args, **kwargs)
      mariadb.OperationalError: Access denied for user 'rh-test'@'10.0.0.4' (using password: YES)

       

       

      This one here is the ultimate error. From here, one never gets a successful connection. The error is exactly the same with mariadb or pymysql.

       

      So I install the package `mysql` using `dnf` which installs mysql client and shared libs.
      Then:

      # pip3.11 install mysql-connector-python
      Collecting mysql-connector-python
        Downloading mysql_connector_python-9.0.0-cp311-cp311-manylinux_2_17_x86_64.whl (19.3 MB)
           ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 19.3/19.3 MB 30.4 MB/s eta 0:00:00
      Installing collected packages: mysql-connector-python
      Successfully installed mysql-connector-python-9.0.0
      WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

       

       

      So the exact same script instead of using `mariadb` I'm using `mysql.connector`. Result:

      [root@rh-test ~]# python3.11 mysql-db-test.py 
      [('rh-user@10.0.0.4',)]

      Works.

       

      `mariadb-db-test.py` uses `mariadb`
      `mysql-db-test.py` uses `mysql.connector`
      Using PyMySQL fails the same as if using mariadb. The error is exactly the same.
      I can reproduce this in any of the EL9 environments tested. Rocky, Alma and RHEL.

              mschorm@redhat.com Michal Schorm
              subedinfo Ricardo Mendes (Inactive)
              Michal Schorm Michal Schorm
              bot rhel-cs-apps-subsystem-qe bot rhel-cs-apps-subsystem-qe
              Votes:
              0 Vote for this issue
              Watchers:
              4 Start watching this issue

                Created:
                Updated: