问题描述
我想从多个线程读取/写入数据库。
经过一番研究,我想起了 ACID 规则。每次我想从线程内部读/写时,我是否都需要调用 myTrans = myConnection.BeginTransaction();
,以保护此事务免受脏读/写(和 myTrans.Commit();
)的影响?在普通 sql 中,我会使用 SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
来保护它。
我如何在 C# 中做到这一点?
提前致谢
解决方法
如果您需要在同一交易中包含多个语句,您只需调用 BeginTransaction()
。对于单个语句的 ACID 规则通常不需要,因为单个会话 - 每次调用 ExecuteReader()/ExecuteScalar()/ExecuteNonQuery()/Fill() - 都会为您提供一个隐式事务。
即使跨越多个语句,我的倾向也是将这些语句放入相同的长 SQL 字符串(或存储过程)中,并包含任何需要的事务指令作为 SQL 的一部分。
就线程安全而言,最好的做法是为每个事务使用一个单独的、全新的连接对象,并将其包装在一个 using
块中。连接不是线程安全的,因此保护它们的方法是为每个线程(或线程中的事务)提供自己的连接,不必共享。
即使在一个线程中,最好不要重复使用相同的连接。有一个称为连接池的功能,您在 C# 代码中看到的连接对象是一个轻量级包装器,用于从池中共享的更重的实际连接。尝试在整个线程或应用程序中重复使用相同的连接对象会以牺牲重物为代价来优化轻量级。