C#.NET MySQL(MariaDB)未保存数据但返回成功

时间:2018-09-27 17:24:04

标签: c# mysql asp.net .net mariadb

即使MysqlClient返回成功且已更新的行数,生产中的间歇性数据(在本地,开发或UAT环境中也不能重复)不会保存到数据库中。

用于生产的应用程序服务器为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个并发用户),即使应用程序从诸如{{1 }},其中x是已更新的行数。

这将通过非常基本的Mysql更新(例如

)发生

int x = Sqlcmd.ExecuteNonQuery();

请忽略明显易写的sql语句,该语句易于sql注入。

其他数据库交互方式(使用事务)也显示相同的行为。

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(); } }

我从上面省略了很多代码(例如,结束部分。)请忽略缺少 //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; } 语句的情况(我99%确信每个连接都是关闭的。)

在未保存数据期间,using {}

中显示以下内容
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 很奇怪...我有一个脚本,每隔0.1秒打印一次此表,并且只有在数据没有保存到数据库时,它才会显示trx_query: NULL(至今)报告它是。)

这一次,trx_query: NULL在TRANSACTIONS部分产生了这个结果...

show engine innodb status

我没有看到任何僵局。

我尝试过的...

  • 由于数据库的操作系统和版本不同,因此我有一个 很难相信这是一个Mysql(MariaDB)问题。
  • 我尝试将Mysql Connector dll从6.9.4更改为6.9.10,然后 6.9.12
  • 我已将应用程序设置为每1小时回收一次其应用程序池 IIS,在回收1分钟后发现了该问题。
  • 我已将------------ 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 的内容注释掉,以便 每.beginTransaction()
  • 之后执行一次默认的AUTO-COMMIT

有人有什么想法吗?

谢谢

**这里编辑是记录到文件中的查询日志(为了保护隐私,我编辑了sql以删除表/列名)

ExecuteNonQuery()

疯狂地看到这么多回滚...可能是什么原因造成的。在下面的评论中,我在app_server> db_server的tcpdump中显示ROLLBACK,所以不是数据库启动这些回滚。

2 个答案:

答案 0 :(得分:0)

好的,我相信我找到了问题。

应用程序经常调用的非常常见的存储过程中包含以下语句...

#include <iostream>
#include <algorithm>
using namespace std;

struct matrix{
    int* data;          //since it is a 1d array which will later be stored in the matrix
    int row, col;
};

void createMatrix(int row, int col, int num[], matrix& mat);    //by reference so that I fetch it by address from memory


matrix operator+ (matrix mat1, matrix mat2){          //Addition
    matrix mat;
    for(int i = 0; i < max(mat1.row*mat1.col, mat2.row*mat2.col); i++){
        mat.data[i] = mat1.data[i] + mat2.data[i];

    }
    return mat;
}

matrix operator- (matrix mat1, matrix mat2){          //Subtraction
    matrix mat;
    for(int i = 0;i < max(mat1.row*mat1.col, mat2.row*mat2.col); i++){
        mat.row = mat1.row - mat2.row;

    }
    return mat;
}

 ostream operator<< (ostream& out, matrix mat){
     for(int i = 0; i < ((mat.row)*(mat.col)); i++){
         if(i % mat.row == 0 ){
             cout<<endl;
         }
         else{out<<mat.data[i]<<" ";}
     }
 }
 int main()
 {
     int row1, col1;
     int row2, col2;

     cout<<"Enter Rows of first matrix: "; cin>>row1;
     cout<<"Enter Cols of first matrix: "; cin>>col1;

     cout<<"Enter Rows of second matrix: "; cin>>row2;
     cout<<"Enter Cols of second matrix: "; cin>>col2;

     int arr1[row1*col1], arr2[row2*col2];
     cout<<"Enter the values you which to add in the first matrix: ";
     for(int i = 0; i < row1*col1; i++){
         cin>>arr1[i];
     }
     cout<<"Enter the values you which to add in the second matrix: ";
     for(int i = 0; i < row2*col2; i++){
         cin>>arr2[i];
     }

     matrix mat1, mat2, mat3;
     createMatrix(row1, col1, arr1, mat1);
     createMatrix(row2, col2, arr2,  mat2);
     mat3 = mat1 + mat2;
    cout<<mat3;

    return 0;
}

void createMatrix(int row, int col, int num[], matrix& mat){
     mat.row = row;
     mat.col = col;
     mat.data = new int [col * row];             //We are trying to make a matrix from a 1d array, so we will stretch the matrix -which is a 2d array
     for(int i = 0; i < col * row; i++){             //in 1-D of size row *col
         mat.data[i] = num[i];                    //Depending on the parameter the data array will be filled dynamically
     }
 }

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

在我运行SP之前,SET AUTOCOMMIT = 0在运行SP后返回了show variables like 'autocommit',它说ON

我的理论是,连接调用SP将其自动提交的会话变量设置为OFF,然后返回到池中。稍后,当连接从池中获取该会话时,它便开始回滚每个语句,因为OFF仍处于关闭状态,并且从未发送过任何明确的autocommit

有人对此有经验吗?

答案 1 :(得分:0)

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