Avoiding deadlocks from higher default isolation level

Default isolation level of TransactionScope is higher than default isolation
of a transaction. This change makes the desired isolation level explicit.

Also adds a feature to experimental which logs additional Sql CE lock
information when an exception is thrown from a web request.

--HG--
branch : dev
extra : rebase_source : 0d9456873e475d87da6e97ae12db0faf5a93232b
This commit is contained in:
Louis DeJardin
2011-03-22 18:07:25 -07:00
parent 319134e237
commit 0660441fc0
4 changed files with 47 additions and 1 deletions

View File

@@ -0,0 +1,35 @@
using System.Linq;
using System.Web.Mvc;
using Orchard.Data;
using Orchard.Environment;
using Orchard.Environment.Extensions;
using Orchard.Logging;
using Orchard.Mvc.Filters;
namespace Orchard.Experimental {
[OrchardFeature("Orchard.Experimental.LockLogging")]
public class LockLogging : FilterProvider, IExceptionFilter {
private readonly Work<ISessionLocator> _sessionLocator;
private readonly ITransactionManager _transactionManager;
public LockLogging(Work<ISessionLocator> sessionLocator) {
_sessionLocator = sessionLocator;
Logger = NullLogger.Instance;
}
public ILogger Logger { get; set; }
public void OnException(ExceptionContext filterContext) {
var connection = _sessionLocator.Value.For(null).Connection;
var command = connection.CreateCommand();
command.CommandText = "SELECT * FROM sys.lock_information";
var reader = command.ExecuteReader();
while (reader.Read()) {
var fields = Enumerable.Range(0, reader.FieldCount)
.Select(i => new { Key = reader.GetName(i), Value = reader.GetValue(i) });
var message = fields.Aggregate("sys.lock_information", (sz, kv) => sz + " " + kv.Key + ":" + kv.Value);
Logger.Debug(message);
}
}
}
}

View File

@@ -21,3 +21,7 @@ Features:
Description: Adds some content definitions to help test lists
Dependencies: Orchard.Lists
Category: Developer
Orchard.Experimental.LockLogging:
Name: Lock Logging
Description: Logs extra diagnostic information for Sql CE if a deadlock timeout occurs
Category: Developer

View File

@@ -39,10 +39,12 @@
<HintPath>..\..\..\..\lib\autofac\Autofac.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="NHibernate, Version=2.1.2.4000, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL" />
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\..\..\lib\aspnetmvc\System.Web.Mvc.dll</HintPath>
@@ -62,6 +64,7 @@
<Compile Include="Controllers\MetadataController.cs" />
<Compile Include="DebugFilter.cs" />
<Compile Include="Handlers\DebugLinkHandler.cs" />
<Compile Include="LockLogging.cs" />
<Compile Include="Migrations.cs" />
<Compile Include="Models\ShowDebugLink.cs" />
<Compile Include="Models\Simple.cs" />

View File

@@ -23,7 +23,11 @@ namespace Orchard.Data {
void ITransactionManager.Demand() {
if (_scope == null) {
Logger.Debug("Creating transaction on Demand");
_scope = new TransactionScope(TransactionScopeOption.Required);
_scope = new TransactionScope(
TransactionScopeOption.Required,
new TransactionOptions {
IsolationLevel = IsolationLevel.ReadCommitted
});
}
}