使用 C# 在 Mysql 上死锁 - “超过锁定等待超时;尝试重新启动事务”

Posted

技术标签:

【中文标题】使用 C# 在 Mysql 上死锁 - “超过锁定等待超时;尝试重新启动事务”【英文标题】:DeadLock on Mysql using C# - "Lock wait timeout exceeded; try restarting transaction" 【发布时间】:2014-01-15 13:57:43 【问题描述】:

我们可以像 SingleTon 一样使用这个类来返回相同的连接和事务(隔离级别读取已提交)(我们使用 CRUD):

public class SharedDbmysql : DatabaseMySQL

    private static DatabaseMySQL sConn;

    private SharedDbMySQL()
    
    

    public static DatabaseMySQL GetInstance()
    
        return GetInstance(TipoDados.Dados);
    

    public static DatabaseMySQL GetInstance(TipoDados OpcoesBD)
    
        if (sConn == null)
            sConn = new DatabaseMySQL(OpcoesBD);
        return sConn;
    

使用 SQL(microsoft)...不会发生错误...只有 Mysql。 我们首先插入“NotaFiscalEntrada”... 在我们在这个方法上插入这个“NotaFiscalEntrada”的产品之后(我们这里有错误):

public static void InsereAtualizaNotaFiscalEntradaProduto(List<nf_entrada_produto> entity, int IDNFEntrada, bool SharedConnection, bool LastOperation)
    
        DatabaseMySQL db;
        MySqlCommand cmd = new MySqlCommand();

        if (SharedConnection)
            db = SharedDbMySQL.GetInstance();
        else
            db = new DatabaseMySQL();

        try
        
            cmd.Connection = db.Conn;
            cmd.Transaction = db.BeginTransaction();
            ONF_Entrada_Produto OpNFProduto = new ONF_Entrada_Produto(cmd);
            foreach (nf_entrada_produto Item in entity)
            
                Item.ValorICMSST = 0;
                Item.IDNFEntrada = IDNFEntrada;
                Item.IDEmpresa = BusinessLogicLayer.ObjetosGlobais.DadosGlobais.EmpresaGlobal.ID;
                if (Item.ID == 0)
                
                    if (!OpNFProduto.Add(Item))
                        throw OpNFProduto.LastError;
                
                else
                
                    if (!OpNFProduto.Update(Item))
                        throw OpNFProduto.LastError;
                
            

            if (LastOperation || !SharedConnection)
            
                db.CommitTransaction();
                db.Disconnect();
            
        
        catch (Exception ex)
        
            db.RollBackTransaction();
            db.Disconnect();
            throw ex;
        
    

错误是当我们插入产品时(上面的代码) “超过锁定等待超时;尝试重新启动事务”。 我们发现了一些关于死锁的问题……连接丢失可能是错误,如何解决?我认为这是服务器错误?谢谢大家。

【问题讨论】:

你的 wait_timeout 设置是什么? 最多 30 秒...我们将其更改为... 1 分钟...但同样的错误。 我和一个朋友谈过......他向我解释说 DatabaseSQLServer db = new DatabaseSQLServer();是一回事...... SqlCommand cmd = new SqlCommand();是其他的...我们使用的是相同的数据库,但每次都会创建 cmd..如果我们使用相同的 CMD,可以解决死锁问题....我们现在正在尝试 你能运行查询SHOW ENGINE INNODB STATUS吗?这应该更准确地说明死锁是什么...... 如果它的事务很多,尝试更频繁地提交,那么锁的活动时间如果少得多。 【参考方案1】:

问题出在方法上...我再次创建了一个新连接,而不是从单例中获取它... 并且数据库死锁表和其他连接也尝试更改它......并且存在问题。

cmd.Connection = new db.Connect();
cmd.Connection = db.Conn;

替换为

cmd.Connection = db.Conn;

类 db(singleton) 内部:

MySqlConnection conn;

public MySqlConnection Conn
        
            get
            
                if ((conn == null) || (conn.State == System.Data.ConnectionState.Closed))
                

                    Connect();
                

                return conn;
            
            set
            
                conn = value;
            
        

public override void Connect()
        
            RetornaDadosIniParaClasse();
            conn = new MySqlConnection(StringConnection);

            try
            
                conn.Open();

                if (conn.State == System.Data.ConnectionState.Closed)
                
                    throw new AccessDatabaseException("Conexão com o banco de dados firebird fechada");
                
            
            catch (Exception ex)
            
                throw new AccessDatabaseException(ex.Message);
            
        

花了很多时间,因为它很难看到错误...我们调试了很多才找到它。

【讨论】:

由于某种原因...问题仅在 MYSQL 上...MSSQL 没有错误...我认为与 c# 交互的 MSSQL 级别具有解决此类问题的机制出于某种原因。

以上是关于使用 C# 在 Mysql 上死锁 - “超过锁定等待超时;尝试重新启动事务”的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 错误:超过锁定等待超时;尝试重新启动事务查询

MySql死锁/提交未在c#中解锁?

为啥在尝试更新 MySQL 条目时出现“超过锁定等待超时”错误?

调用某些查询时,MySQL“超过锁定等待超时”

mysql_query("START TRANSACTION")- 超过锁定等待超时;尝试在 Codeigniter Mysql 中重新启动事务

超过锁定等待超时;尝试重新启动事务 MYSQL Python