草庐IT

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

coder 2023-10-26 原文

即使 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 个并发用户)系统将开始不保存对数据库的更改,即使应用程序从诸如 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注入(inject)的明显写得不好的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) 问题。
  • 我尝试将 Mysql Connector dll 从 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
    

    看到这么多回滚真是太疯狂了……这是什么原因造成的。在我下面的评论中,我在 app_server > db_server 中的 tcpdump 中显示 ROLLBACK,因此它不是启动这些回滚的数据库。

    最佳答案

    好的,我相信我发现了问题。

    应用程序经常调用的一个非常常见的存储过程中有这个语句......

    START TRANSACTION;
    SET AUTOCOMMIT = 0;
    

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

    在我运行 SP 之前,show variables like 'autocommit'返回 ON SP运行后,它说OFF
    我的理论是调用该 SP 的连接将其自动提交的 session 变量设置为 OFF然后回到游泳池。稍后,当连接从池中获取该 session 时,它开始回滚每个语句,因为 autocommit仍然关闭,并且没有明确的 COMMIT;曾经被发送过。

    任何人都有这方面的经验?

    关于C# .NET MySQL (MariaDB) 不保存数据但返回成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52542197/

    有关C# .NET MySQL (MariaDB) 不保存数据但返回成功的更多相关文章

    1. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

      我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

    2. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

      为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

    3. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

      我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

    4. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

      我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

    5. ruby - 如何验证 IO.copy_stream 是否成功 - 2

      这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

    6. ruby - Ruby 有 `Pair` 数据类型吗? - 2

      有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

    7. ruby - Ruby 中的隐式返回值是怎么回事? - 2

      所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

    8. ruby-on-rails - ruby 日期方程不返回预期的真值 - 2

      为什么以下不同?Time.now.end_of_day==Time.now.end_of_day-0.days#falseTime.now.end_of_day.to_s==Time.now.end_of_day-0.days.to_s#true 最佳答案 因为纳秒数不同:ruby-1.9.2-p180:014>(Time.now.end_of_day-0.days).nsec=>999999000ruby-1.9.2-p180:015>Time.now.end_of_day.nsec=>999999998

    9. ruby - 从 String#split 返回的零长度字符串 - 2

      在Ruby1.9.3(可能还有更早的版本,不确定)中,我试图弄清楚为什么Ruby的String#split方法会给我某些结果。我得到的结果似乎与我的预期相反。这是一个例子:"abcabc".split("b")#=>["a","ca","c"]"abcabc".split("a")#=>["","bc","bc"]"abcabc".split("c")#=>["ab","ab"]在这里,第一个示例返回的正是我所期望的。但在第二个示例中,我很困惑为什么#split返回零长度字符串作为返回数组的第一个值。这是什么原因呢?这是我所期望的:"abcabc".split("a")#=>["bc"

    10. ruby - 我如何添加二进制数据来遏制 POST - 2

      我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

    随机推荐