簡體   English   中英

C#.NET MySQL(MariaDB)還沒有保存數據但是還原成功

[英]C# .NET MySQL (MariaDB) Not Saving Data Yet Returning Sucess

間歇性地生產(在本地,開發或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 | +-------------------------+----------------------------------+ +-------------------------+----------------------------------+ | 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是非常奇怪的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)問題。
  • 我已經嘗試將Mysql Connector dll從6.9.4更改為6.9.10和6.9.12
  • 我已經將應用程序設置為在IIS中每1小時回收一次應用程序池,問題已在回收后1分鍾看到。
  • 我已經注釋掉.beginTransaction()東西,所以在每個ExecuteNonQuery()之后執行默認的AUTO-COMMIT

有人有想法么?

謝謝

**編輯這里是記錄到文件的查詢日志(我編輯了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

很難看到這么多ROLLBACKS ......可能是什么導致了這一點。 在下面的評論中,我在app_server> db_server中的tcpdump中顯示ROLLBACK,因此不是啟動這些回滾的數據庫。

好吧,我相信我發現了問題。

應用程序調用的一個非常常見的存儲過程中有這個聲明......

START TRANSACTION;
SET AUTOCOMMIT = 0;

我從另一篇文章中了解到SET AUTOCOMMIT = 0是不必要的(很可能是我的罪魁禍首。)

在我運行SP之前,在SP運行后show variables like 'autocommit'返回ON ,它說OFF

我的理論是連接調用SP將其autocommit的會話變量設置為OFF然后返回到池中。 稍后,當一個連接從池中獲取該會話時,它開始回滾每個語句,因為autocommit仍然關閉,並且沒有顯式的COMMIT; 曾被送過。

有人有這方面的經驗嗎?

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'.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM