我们在MySQL中使用InnoDB有一个表,我们使用的是事务隔离级别read uncommitted.为什么设置@x如图所示获得锁定?
mysql> set @x = (select userID from users limit 1);
Query OK, 0 rows affected (0.02 sec)
mysql>
Run Code Online (Sandbox Code Playgroud)
尝试从另一个提示更新此表会导致超时错误:
mysql> update users set userID = 1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
Run Code Online (Sandbox Code Playgroud) 我们遇到一些显然以错误的隔离级别执行的数据库代码的问题.在代码的这个特定部分中,它应该以"READ UNCOMMITTED"执行以最小化锁.此时数据不一致是可以的.
但是,代码实际上是使用READ COMMITTED读取的,我们无法弄清楚原因.
这是我们做的:
在断点处,我们向数据库发出以下命令:
select s.session_id, s.transaction_isolation_level, st.text from sys.dm_exec_sessions s
inner join sys.sysprocesses sp on (sp.spid = s.session_id)
CROSS APPLY sys.dm_exec_sql_text(sp.sql_handle) st
Run Code Online (Sandbox Code Playgroud)
这个SQL现在报告了4个池化连接,其中一个是我们的连接,我们可以超越断点来执行我们的SQL,具有以下状态:
53 2 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED
Run Code Online (Sandbox Code Playgroud)
即.会话53具有隔离级别2(READ COMMITTED),并且在此会话上执行的最后一个SQL是"SET TRANSACTION ..."命令.
怎么会这样?
我们使用SQL事件探查器验证了在我们的.NET代码打开它之前这个连接没有生效,所以它没有从连接池中重用.
然而,通过新的连接,并且在其上执行的唯一和第一个SQL明确告诉它使用READ UNCOMMITTED,连接如何仍然是READ COMMITTED?
我们应该在这看什么?
连接字符串(带有编辑的位)如下所示:
SERVER=hostname;DATABASE=dbname;Integrated Security=false;USER ID=sa;PASSWORD=****;Application Name=appname;Type System Version=SQL Server 2000;Workstation ID=hostname;
Run Code Online (Sandbox Code Playgroud)
连接是正常SqlConnection连接,以正常方式打开.
不幸的是,如果我们编写打开SqlConnection的正常代码,我们就无法重现问题,所以必须有应用程序状态的东西,但是因为SqlProfiler和Sql Server都告诉我们是,所以SQL被执行了,但是没有,我不在乎.
有什么可以影响这个?
完全相同的代码也打开其他连接,即代码执行多次并打开许多连接,因此多个连接最终在池中,但只有第一个连接最终出现此问题.
这是SQL Server 2008 R2,我们也在2012年重现了这个问题.
编辑
好的,还有一些信息.
首先,我们正在启用池化,或者更确切地说,我们没有明确禁用池,也没有将连接字符串弄为"N"池.
但是,此连接是第一个使用此特定连接字符串打开的连接,因此不会从池中检索它.另请参阅我的下面的说明,它永远"生病".
此连接正在设置如下:
var …Run Code Online (Sandbox Code Playgroud) 只需阅读Omar在他的博客Linq上的这篇有趣的文章,使用未提交的读取解决事务死锁和查询超时问题,最后Javed Hasan开始与他讨论他在高容量网站上解决nolock情况的问题.
在这里,试图解决的问题是,从sql意义上我们需要使用带有NOLOCK的Select语句或使用SET TRANSACTION LEVEL READ UNCOMMITTED,否则在DB中的高容量行将被锁定并导致错误.Omar使用的技术是Linq2Sql,所以问题是我们如何在你的C#数据访问代码中实现这一点,所以上述情况不会发生?
基本上在帖子中,Omar通过在现实世界网站上使用SqlProfiler等工具进行工作和测试来解决他的问题,而Javed Hasan则使用MSDN文档和Scott Hanselman的博客文章等来解决他的问题.
奥马尔建议使用以下内容
using (var db = new DropthingsDataContext2())
{
db.Connection.Open();
db.ExecuteCommand("SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;");
var user = db.aspnet_Users.First();
var pages = user.Pages.ToList();
}
Run Code Online (Sandbox Code Playgroud)
而Javed Hasan表示
using (new TransactionScope(TransactionScopeOption.Required,
new TransactionOptions { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
//Your db Operation
}
Run Code Online (Sandbox Code Playgroud)
我非常有兴趣知道你们在这个特定问题上你们在StatckOverflow这样的高容量网站上做了什么,或者杰夫和他们的家伙在这方面做了什么?
编辑:在阅读完第一篇文章后,我想在奥马尔的帖子中指出一些内容.
sql-server nolock transactionscope read-uncommitted linq-to-sql
我需要在正在进行的事务中启动新事务,以便第二个事务中的异常只会回滚新事务而不是旧事务。
这是我通过在第二个事务中设置传播属性来做的,如下所示:
@Transactional(传播 = 传播.REQUIRES_NEW)
这创建了一个新事务,但新事务需要读取第一个事务的一些未提交数据(脏读),并更新该数据。我试图通过将隔离属性设置为:
@Transactional(propagation = Propagation.REQUIRES_NEW,isolation=Isolation.READ_UNCOMMITTED)
这将引发异常 - InvalidIsolationLevelException,表示“标准 JPA 不支持自定义隔离级别 - 为您的 JPA 实现使用特殊的 JpaDialect”。
任何人都可以帮助我实施 JpaDialect 吗?我正在使用 Eclipse Link 2.5.1 。
或者我可以在开始新交易之前如何关闭第一笔交易?由于第一个事务已关闭,因此第二个事务读取第一个事务提交的数据没有问题。
jpa transactional eclipselink transaction-isolation read-uncommitted
在MSSQL 2008上使用EF进行查询更新时,存在性能和锁定问题.所以我把ReadUncommitted事务隔离级别,希望解决它,像这样,
之前
using (myEntities db = new myEntities())
{
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact; // large results
for (var item I data)
item.Flag = 0;
db.SaveChanges(); // Probably db lock
}
Run Code Online (Sandbox Code Playgroud)
后
using (var scope =
new TransactionScope(TransactionScopeOption.RequiresNew,
new TransactionOptions() { IsolationLevel = IsolationLevel.ReadUncommitted }))
{
using (myEntities db = new myEntities ())
{
var data = from _Contact in db.Contact where _Contact.MemberId == 13 select _Contact; …Run Code Online (Sandbox Code Playgroud) c# sql-server transactionscope read-uncommitted entity-framework-6
我不能在连接语句中的表名后使用 NOLOCK。尝试通过 JOIN 读取未提交的数据是否是一个有效的场景
我试图了解已提交读和未提交读隔离级别。我知道理论上读未提交允许脏读而提交读不允许,但我仍然无法真正理解。

考虑上图,如果没有任何事务被中止,那么对于已提交读和未提交读的最终结果是否相同?
我们可以像这样使用SQL:
SELECT * FROM student WITH(NOLOCK);
Run Code Online (Sandbox Code Playgroud)
如何在不使用LINQ to SQL的情况下实现这一点TransactionScope?
我编写了一个函数,它mytable根据参数在表中创建一行,并返回创建的行的id.
不幸的是,如果我使用以下语句,则SELECT返回no行,就好像该函数的事务不同于其中一个SELECT.
SELECT * FROM mytable WHERE id = createComplexRow(...);
Run Code Online (Sandbox Code Playgroud)
我的理解是我为select和函数运行相同的事务,然后应该能够读取未提交的行.
我正在尝试使用postgres 9.6
任何线索如何让它正常工作?
sql-server ×4
transactions ×3
linq-to-sql ×2
sql ×2
.net ×1
c# ×1
eclipselink ×1
function ×1
join ×1
jpa ×1
locking ×1
locks ×1
mysql ×1
nolock ×1
oracle ×1
postgresql ×1