使用 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_query("START TRANSACTION")- 超过锁定等待超时;尝试在 Codeigniter Mysql 中重新启动事务