为什么内部 TransactionScope 的 IsolationLevel 不能不同,而 SQL 事务可以不同?
Why inner TransactionScope's IsolationLevel cannot be different, while SQL transactions can be?
在数据库事务中更改隔离级别是可以的,包括将一个事务加入已经 运行 的情况。
从现在开始,您只需更改处理锁的方式即可。使用 Sql 服务器,运行没有问题:
begin transaction
set transaction isolation level serializable;
select * from FooTable;
set transaction isolation level read committed;
select * from FooTable;
begin transaction
set transaction isolation level serializable;
select * from FooTable;
--transaction_isolation_level can be observed as 4 (serializable)
但是,当使用 .NET TransactionScope 在上述 Sql 服务器中创建交易时,像这样(C#、xUnit):
[Theory]
[AutoFixtureMagicToGetParameterInstances]
void ZmenaIzolacniUrovneVedeKVyjimce(IFooDao sut, Foo foo)
{
var tranOpts = new TransactionOptions()
{
IsolationLevel = IsolationLevel.Serializable,
Timeout = TimeSpan.FromSeconds(60)
};
var tranOpts2 = new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadCommitted,
Timeout = TimeSpan.FromSeconds(60)
};
using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, tranOpts))
{
sut.SelectFoos();
using (var transactionScope2 = new TransactionScope(TransactionScopeOption.Required, tranOpts2))
{
sut.SelectFoos();
}
}
}
导致异常:
System.ArgumentException : The transaction specified for TransactionScope has a different IsolationLevel than the value requested for the scope.
Parameter name: transactionOptions.IsolationLevel
为什么 TransactionScope 的设计者认为有必要立即抛出异常?
我希望至少只要只涉及数据库资源,行为就会相同。
是否有关于 TransactionScope 的内容我遗漏了,或者仅仅是因为无法保证所有可能的征用资源的合理行为?
如此处评论所述Inner TransactionScope with different IsolationLevel, how can it be achieved?
TransactionScope is not limited to use with SQL Server, it can allow
distributed transactions across processes/systems. So it is stricter
than what SQL Server allows, likely to simplify the complexity of
ensuring consistency across the systems than support distributed
transactions. – AaronLS
所以答案基本上似乎可以归结为 "TransactionScope may have way more on it's plate than just database transaction and so it forbids complexities like changing isolation levels"。
在数据库事务中更改隔离级别是可以的,包括将一个事务加入已经 运行 的情况。 从现在开始,您只需更改处理锁的方式即可。使用 Sql 服务器,运行没有问题:
begin transaction
set transaction isolation level serializable;
select * from FooTable;
set transaction isolation level read committed;
select * from FooTable;
begin transaction
set transaction isolation level serializable;
select * from FooTable;
--transaction_isolation_level can be observed as 4 (serializable)
但是,当使用 .NET TransactionScope 在上述 Sql 服务器中创建交易时,像这样(C#、xUnit):
[Theory]
[AutoFixtureMagicToGetParameterInstances]
void ZmenaIzolacniUrovneVedeKVyjimce(IFooDao sut, Foo foo)
{
var tranOpts = new TransactionOptions()
{
IsolationLevel = IsolationLevel.Serializable,
Timeout = TimeSpan.FromSeconds(60)
};
var tranOpts2 = new TransactionOptions()
{
IsolationLevel = IsolationLevel.ReadCommitted,
Timeout = TimeSpan.FromSeconds(60)
};
using (var transactionScope = new TransactionScope(TransactionScopeOption.Required, tranOpts))
{
sut.SelectFoos();
using (var transactionScope2 = new TransactionScope(TransactionScopeOption.Required, tranOpts2))
{
sut.SelectFoos();
}
}
}
导致异常:
System.ArgumentException : The transaction specified for TransactionScope has a different IsolationLevel than the value requested for the scope.
Parameter name: transactionOptions.IsolationLevel
为什么 TransactionScope 的设计者认为有必要立即抛出异常?
我希望至少只要只涉及数据库资源,行为就会相同。 是否有关于 TransactionScope 的内容我遗漏了,或者仅仅是因为无法保证所有可能的征用资源的合理行为?
如此处评论所述Inner TransactionScope with different IsolationLevel, how can it be achieved?
TransactionScope is not limited to use with SQL Server, it can allow distributed transactions across processes/systems. So it is stricter than what SQL Server allows, likely to simplify the complexity of ensuring consistency across the systems than support distributed transactions. – AaronLS
所以答案基本上似乎可以归结为 "TransactionScope may have way more on it's plate than just database transaction and so it forbids complexities like changing isolation levels"。