Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server NHibernate下的SQL Server死锁_Sql Server_Nhibernate_Transactions_Locking_Isolation Level - Fatal编程技术网

Sql server NHibernate下的SQL Server死锁

Sql server NHibernate下的SQL Server死锁,sql-server,nhibernate,transactions,locking,isolation-level,Sql Server,Nhibernate,Transactions,Locking,Isolation Level,我有一个多线程应用程序,可以处理大型数据库(文件大小>1GB,数据库有38个表,每个表有超过500K的实体)。它使用了Castle 3.1.0.0、NHibernate 3.3.1.4000、FluentNibernate 1.3.0.733、SQL Server 2012 NHibernate以下一种方式配置: config.SetProperty(Environment.CommandTimeout, "300"); config.SetProperty(Environment.BatchS

我有一个多线程应用程序,可以处理大型数据库(文件大小>1GB,数据库有38个表,每个表有超过500K的实体)。它使用了Castle 3.1.0.0、NHibernate 3.3.1.4000、FluentNibernate 1.3.0.733、SQL Server 2012

NHibernate以下一种方式配置:

config.SetProperty(Environment.CommandTimeout, "300");
config.SetProperty(Environment.BatchSize, "0"); 
config.SetProperty(Environment.GenerateStatistics, "true");
config.SetProperty(Environment.ReleaseConnections, "auto");
config.SetProperty(Environment.UseQueryCache, "true");
config.SetProperty(Environment.SqlExceptionConverter, typeof(MsSqlExceptionConverter).AssemblyQualifiedName);
//...
.MaxFetchDepth(1)
我使用每个线程一个会话(Castle.Windsor)和短事务。每个数据库更新、保存、删除过程都由代码锁定:

public abstract class BaseEntityRepository<T, TId> : IBaseEntityRepository<T, TId> where T : BaseEntity<TId> {
    protected static readonly object Locker = new object();

    public bool Save(T item) {
        bool result = false;

        if ((item != null) && (item.IsTransient())) {
            lock (Locker) {
                using (ITransaction tr = Session.BeginTransaction()) {
                    try {                       
                        Session.Save(item);
                        if ((tr.IsActive) && (!tr.WasCommitted) && (!tr.WasRolledBack))
                            tr.Commit();  
                        result = true;
                    } catch {
                        if ((tr.IsActive) && (!tr.WasCommitted) && (!tr.WasRolledBack))
                            tr.Rollback();
                        Session.Clear();
                        throw;
                    }
                }
            }
        }
        return result;
    }

    //same for delete and update 

    public T Get(TId itemId) {
        T result = default(T);

        try {
            result = Session.Get<T>(itemId);
        } catch {
            throw;
        }
        return result;
    }

    public IList<T> Find(Expression<Func<T, bool>> predicate) {
        IList<T> result = new List<T>();
        try {
            result = Session.Query<T>().Where(predicate).ToList();
        } catch {
            throw;
        }
        return result;
    }
}
无法将数据库状态与会话同步 NHibernate.StaleObjectStateException:行被另一个事务更新或删除(或未保存的值映射不正确):[Foo\544353]

NHibernate.TransactionException:事务未连接或已断开连接

我没有DB实体的Version属性,代码中也没有OptimisticLock.Version()行,所以我使用了悲观锁隐式。我可以添加版本乐观锁,但我认为这不会解决问题

我试着做一个简单的测试:

Thread t1 = new Thread(m1);
Thread t2 = new Thread(m2);
t1.Start();
t2.Start();

private static void m1() {
    FooRepository rep1 = BootstrapContainer.Instance.Resolve<FooRepository>();
    Foo foo1 = rep1.Get(1);
    foo1.Field1 = "bbbb";
    Thread.Sleep(60*1000);
    rep1.Update(foo1);
}

private static void m2() {
    FooRepository rep2 = BootstrapContainer.Instance.Resolve<FooRepository>();
    Thread.Sleep(5*1000);
    Foo foo2 = rep2.Get(1);
    foo2.Field2 = "aaaaa";
    Thread.Sleep(5*1000);
    rep2.Update(foo2);
}
螺纹t1=新螺纹(m1);
螺纹t2=新螺纹(m2);
t1.Start();
t2.Start();
私有静态void m1(){
FooRepository rep1=BootstrapContainer.Instance.Resolve();
Foo foo1=rep1.Get(1);
foo1.Field1=“bbbb”;
线程。睡眠(60*1000);
rep1.更新(foo1);
}
私有静态void m2(){
FooRepository rep2=BootstrapContainer.Instance.Resolve();
线程。睡眠(5*1000);
Foo foo2=rep2.Get(1);
foo2.Field2=“AAAA”;
线程。睡眠(5*1000);
rep2.更新(foo2);
}
一切正常,没有任何错误


为什么我会有这些错误(我没有更改代码,只是将数据库合并到一个数据库中,并且在合并之前,所有这些都可以正常工作)?如果我使用锁定来防止同时更新不同线程中的实体,为什么会出现这种错误。

您可以从查询并行化中获得死锁。。。也就是说,当一个查询将工作拆分为多个并行操作时,它可能会针对自身死锁。我有好几次遇到过这种情况。如果您使用的是hql,那么可以将选项(MAXDOP 1)添加到查询/语句中,以查看这是否解决了问题


或者,您可以将整个服务器设置为MAXDOP 1。。。这意味着您将永远无法获得并行性()。如果不深入分析工作负载,我不建议这样做,但它可以帮助您了解并行性是否是死锁的根源。

您咨询过DBA吗?您是否重新创建了索引并缩减了磁盘空间?当您运行测试,但将每个线程中的同一字段更新为不同的值时,会发生什么情况?将foo1.Field1=“bbbb”和foo2.Field1设置为“aaaaa”。
in NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
in NHibernate.Persister.Entity.AbstractEntityPersister.UpdateOrInsert(Object id, Object[] fields, Object[] oldFields, Object rowId, Boolean[] includeProperty, Int32 j, Object oldVersion, Object obj, SqlCommandInfo sql, ISessionImplementor session)
in NHibernate.Persister.Entity.AbstractEntityPersister.Update(Object id, Object[] fields, Int32[] dirtyFields, Boolean hasDirtyCollection, Object[] oldFields, Object oldVersion, Object obj, Object rowId, ISessionImplementor session)
in NHibernate.Action.EntityUpdateAction.Execute()
in NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
in NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
in NHibernate.Engine.ActionQueue.ExecuteActions()
in NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
in NHibernate.Transaction.AdoTransaction.CheckNotZombied()
in NHibernate.Transaction.AdoTransaction.Rollback()
in My.DBLayer.Data.Repositories.BaseEntityRepository`2.Update(T item)
Thread t1 = new Thread(m1);
Thread t2 = new Thread(m2);
t1.Start();
t2.Start();

private static void m1() {
    FooRepository rep1 = BootstrapContainer.Instance.Resolve<FooRepository>();
    Foo foo1 = rep1.Get(1);
    foo1.Field1 = "bbbb";
    Thread.Sleep(60*1000);
    rep1.Update(foo1);
}

private static void m2() {
    FooRepository rep2 = BootstrapContainer.Instance.Resolve<FooRepository>();
    Thread.Sleep(5*1000);
    Foo foo2 = rep2.Get(1);
    foo2.Field2 = "aaaaa";
    Thread.Sleep(5*1000);
    rep2.Update(foo2);
}