C # .NET MySQL (MariaDB) пока не сохраняет данные, возвращая успех - PullRequest
0 голосов
/ 27 сентября 2018

Периодически производственные (не повторяемые в локальной среде, среде dev или UAT) данные не сохраняются в базе данных, даже если MysqlClient возвращает успех и число строк обновлено.

Сервер приложений для производстваIIS 7 on Windows Server 2008

Этот сервер приложений взаимодействует с 2 отдельными серверами баз данных.

Один на Ubuntu Linux servername 4.15.0-23-generic #25-Ubuntu SMP Wed May 23 18:02:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux +-------------------------+----------------------------------+ | Variable_name | Value | +-------------------------+----------------------------------+ | innodb_version | 5.6.39-83.1 | | protocol_version | 10 | | slave_type_conversions | | | version | 10.1.34-MariaDB-0ubuntu0.18.04.1 | | version_comment | Ubuntu 18.04 | | version_compile_machine | x86_64 | | version_compile_os | debian-linux-gnu | | version_malloc_library | system jemalloc | | version_ssl_library | YaSSL 2.4.4 | | wsrep_patch_version | wsrep_25.23 | +-------------------------+----------------------------------+

И другой на Fedora Linux servername 4.8.13-100.fc23.x86_64 #1 SMP Fri Dec 9 14:51:40 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

+-------------------------+-----------------+ | Variable_name | Value | +-------------------------+-----------------+ | innodb_version | 5.6.32-79.0 | | protocol_version | 10 | | slave_type_conversions | | | version | 10.0.28-MariaDB | | version_comment | MariaDB Server | | version_compile_machine | x86_64 | | version_compile_os | Linux | | version_malloc_library | system | +-------------------------+-----------------+

Хех, пожалуйста, не спрашивайте о совершенно разных серверах баз данных.В любом случае, они оба имеют одинаковые проблемы.

Приложение находится в .NET 4.5 и использует MysqlConnector Mysql.Data dll 6.9.4 для связи с обеими базами данных.

Спорадически (при большой нагрузке (с точки зрения того, чтосистема обычно получает); около 25 одновременно работающих пользователей) система начинает не сохранять изменения в базе данных, даже если приложение возвращается из кода, такого как int x = Sqlcmd.ExecuteNonQuery();, где x - количество обновленных строк.

Это произойдет с очень простыми обновлениями Mysql, такими как

MySqlConnection conn = new MySqlConnection(TheConnectionString()); conn.Open(); try { string Query = "DELETE FROM A_TABLE WHERE USERID = '" + UserID + "'"; MySqlCommand Sqlcmd = new MySqlCommand(Query, conn); Sqlcmd.CommandText = Query; Sqlcmd.ExecuteNonQuery(); } finally { if (conn != null) { conn.Close(); conn.Dispose(); } }

Пожалуйста, не обращайте внимания на явно плохой письменный оператор SQL, который склонен к внедрению SQL.

Другие способы взаимодействия с базой данных (с использованием транзакций) также демонстрируют такое же поведение.

    //Create and Instantiate the Connection
        sqlConnection = new MySqlConnection(strConnect);
        sqlConnection.Open();

        //With Transaction
        if (bWithTrans == true)
        {
            sqlTransaction = sqlConnection.BeginTransaction();
            //sqlTransaction.IsolationLevel = IsolationLevel.
            bRollBack = false; // Reset indicator
        }

        sqlCommand = new MySqlCommand(qryString, sqlConnection);
        sqlCommand.CommandText = qryString;

        //With Transaction
        if (bWithTrans == true)
        {
            sqlCommand.Transaction = sqlTransaction;
        }
...
...
       if (IsInTransaction())
        {
            if (bRollBack == true)
            {
                sqlTransaction.Rollback();
            }
            else
            {
                sqlTransaction.Commit();
            }
            sqlTransaction.Connection.Close();
            sqlTransaction.Connection.Dispose();
            sqlTransaction = null;
        }

Я пропустил много кода из вышеперечисленного (например, заключительную часть). Пожалуйста, не обращайте внимания на отсутствие оператора using {} (я на 99% уверен, что каждое соединение закрыто.)

Во время, когда данные не сохраняются, в select * from information_schema.innodb_trx

*************************** 1. row ***************************
                    trx_id: 302303150
                 trx_state: RUNNING
               trx_started: 2018-09-27 08:56:45
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 0
       trx_mysql_thread_id: 117343
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 0
     trx_lock_memory_bytes: 360
           trx_rows_locked: 0
         trx_rows_modified: 0
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 10000
          trx_is_read_only: 0
trx_autocommit_non_locking: 0
*************************** 1. row ***************************
                    trx_id: 302303150
                 trx_state: RUNNING
               trx_started: 2018-09-27 08:56:45
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 0
       trx_mysql_thread_id: 117343
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 0
     trx_lock_memory_bytes: 360
           trx_rows_locked: 0
         trx_rows_modified: 0
   trx_concurrency_tickets: 0
       trx_isolation_level: REPEATABLE READ
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 10000
          trx_is_read_only: 0
trx_autocommit_non_locking: 0

появляется следующее странное сообщение trx_query: NULL очень странно видеть ... У меня есть скрипт для печати этоготаблица каждые 0,1 секунды, и она будет отображать ТОЛЬКО trx_query: NULL, когда данные не сохраняются в базе данных (но сообщают, что это так).

В течение этого времени show engine innodb status создает это в разделе TRANSACTIONS...

------------
TRANSACTIONS
------------
Trx id counter 147254697
Purge done for trx's n:o < 147254674 undo n:o < 0 state: running but idle
History list length 30
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0, not started
MySQL thread id 222904, OS thread handle 0x7f7a6e08b700, query id 617593737 localhost root init
show engine innodb status
---TRANSACTION 147254688, not started
MySQL thread id 222902, OS thread handle 0x7f7a23a5f700, query id 617593732 10.22.18.39 DB_NAME
---TRANSACTION 147254696, not started
MySQL thread id 222901, OS thread handle 0x7f7a239c9700, query id 617593736 10.22.18.39 DB_NAME
---TRANSACTION 147254644, not started
MySQL thread id 222900, OS thread handle 0x7f7a6e027700, query id 617593526 10.22.18.39 DB_NAME
---TRANSACTION 147254684, not started
MySQL thread id 222897, OS thread handle 0x7f7a6b4e9700, query id 617593709 10.22.18.39 DB_NAME
---TRANSACTION 147240473, not started
MySQL thread id 126445, OS thread handle 0x7f7a23af5700, query id 617593614 10.22.18.41 DB_NAME
---TRANSACTION 84024323, not started
MySQL thread id 1, OS thread handle 0x7f7a6e185700, query id 0 Waiting for background binlog tasks
---TRANSACTION 147254695, ACTIVE 1 sec fetching rows
mysql tables in use 1, locked 0
MySQL thread id 222898, OS thread handle 0x7f7a239fb700, query id 617593734 10.22.18.39 DB_NAME Sending data
SELECT COUNT(*) FROM TABLE I'M HIDING FOR PRIVACY
Trx read view will not see trx with id >= 147254696, sees < 147254696
Trx #rec lock waits 0 #table lock waits 0
Trx total rec lock wait time 0 SEC
Trx total table lock wait time 0 SEC

Я не вижу ничего с точки зрения тупика.

То, что я пробовал ...

  • Со времен БДразличаются с точки зрения ОС и версий, мне трудно поверить, что это проблема Mysql (MariaDB).
  • Я пытался изменить dll Mysql Connector с 6.9.4 на 6.9.10 и 6.9.12
  • Я настроил приложение на перезапуск его пула приложений каждые 1 час в IIS, проблема видна 1 минутуПосле переработки.
  • Я закомментировал материал .beginTransaction(), так что AUTO-COMMIT по умолчанию выполняется после каждого ExecuteNonQuery()

У кого-нибудь есть какие-нибудь идеи?

Спасибо

** измените здесь журнал запросов, записанный в файл (я отредактировал sql, чтобы удалить имена таблиц / столбцов для конфиденциальности)

245133 Query    ROLLBACK
                245671 Connect  root@localhost as anonymous on
                245671 Query    select * from information_schema.innodb_trx
                244093 Query    ROLLBACK
                245671 Quit
                245133 Init DB  DB_NAME
                245133 Query    SELECT `DESC` as Status FROM TABLE WHERE REC_NUM != 2 ORDER BY `REC_NUM`
                245133 Query    ROLLBACK
                244093 Init DB  DB_NAME
                244093 Query    SELECT COLUMN FROM TABLE WHERE COLUMN IN (SELECT COLUMN FROM TABLE WHERE STATUSCODE = 3) ORDER BY COLUMN
                244093 Query    ROLLBACK
                245133 Init DB  DB_NAME
                245133 Query    SELECT COLUMN FROM TABLE GROUP BY COLUMN ORDER BY COLUMN
                245133 Query    ROLLBACK
                244093 Init DB  DB_NAME
                244093 Query    SELECT COLUMN as Status FROM TABLE WHERE COLUMN <> 1 AND COLUMN <> 2 AND COLUMN <> 4 AND COLUMN <> 10 AND COLUMN <> 11
AND COLUMN <> 12 AND COLUMN <> 13  AND COLUMN <> 15 ORDER BY REC_NUM
                244093 Query    ROLLBACK
                245133 Init DB  DB_NAME
                245133 Query    SELECT COLUMN FROM TABLE WHERE COLUMN = 'DB_NAME'
                245133 Query    ROLLBACK
                245248 Query    ROLLBACK
                244093 Init DB  DB_NAME
                245133 Init DB  DB_NAME

Сумасшедшийувидеть так много роллбэков ... что может быть причиной этого.В моем комментарии ниже я показываю ROLLBACK в tcpdump в app_server> db_server, поэтому это не БД, инициирующая эти откаты.

Ответы [ 2 ]

0 голосов
/ 04 октября 2018
SELECT  COLUMN
    FROM  TABLE
    WHERE  COLUMN IN (
        SELECT  COLUMN
            FROM  TABLE
            WHERE  STATUSCODE = 3
                     )
    ORDER BY  COLUMN

->

SELECT column
    FROM table
    WHERE statuscode = 3
    ORDER BY column;

(Если на самом деле есть две разные таблицы, то , пожалуйста, , проясните это в своем вопросе.В этом случае для улучшенного запроса потребуется JOIN.)

SELECT  COLUMN
    FROM  TABLE
    GROUP BY  COLUMN
    ORDER BY  COLUMN

->

SELECT DISTINCT column
    FROM table
    ORDER BY column

и

SELECT  COLUMN as Status
    FROM  TABLE
    WHERE  COLUMN <> 1
      AND  COLUMN <> 2
      AND  COLUMN <> 4
      AND  COLUMN <> 10
      AND  COLUMN <> 11
      AND  COLUMN <> 12
      AND  COLUMN <> 13
      AND  COLUMN <> 15
    ORDER BY  REC_NUM

->

SELECT column AS Status
    FROM table
    WHERE column NOT IN (1,2,4,10,11,12,13,15)
    ORDER BY rec_num

и

Why do this; the answer is obviously 'DB_NAME':

SELECT column FROM table WHERE column = 'DB_NAME'.
0 голосов
/ 27 сентября 2018

Хорошо, я думаю, что нашел проблему.

Очень распространенная хранимая процедура, которую приложение часто вызывает, содержала в себе это утверждение ...

START TRANSACTION;
SET AUTOCOMMIT = 0;

Я узнал отв другом сообщении о том, что SET AUTOCOMMIT = 0 не является необходимым (и, скорее всего, моим виновником).

До того, как я запустил SP, show variables like 'autocommit' вернул ON после того, как SP запустился, говорится: OFF

Моя теория состоит в том, что соединения, которые вызвали, чтобы переменная сеанса автоматической фиксации SP была установлена ​​на OFF, а затем вернулись в пул.Позже, когда соединение получило этот сеанс из пула, оно начало откатывать все операторы, потому что autocommit все еще был отключен, и явное COMMIT; никогда не отправлялось.

Кто-нибудь имел опыт с этим?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...