using (var session = NhibernateHelper.OpenSession()) using (var transaction = session.BeginTransaction()) { session.Lock(mall,LockMode.None); var voucher = new Voucher(); voucher.FirstName = firstName ?? string.Empty; voucher.LastName = lastName ?? string.Empty; voucher.Address = address ?? string.Empty; voucher.Address2 = address2 ?? string.Empty; voucher.City = city ?? string.Empty; voucher.State = state ?? string.Empty; voucher.Zip = zip ?? string.Empty; voucher.Email = email ?? string.Empty; voucher.Mall = mall; session.Save(voucher); var issued = session.CreateCriteria<Voucher>() .Add(Restrictions.Eq("Mall",mall)) .SetProjection(Projections.Count("ID")) .UniqueResult<int>(); if (issued >= mall.TotalVouchers) { transaction.Rollback(); throw new VoucherLimitException(); } transaction.Commit(); return voucher; }
但是,我遇到了很多僵局.我认为这是因为我正在尝试计算表中的记录,我刚刚执行了插入操作,并且仍然在插入的行上保持锁定,从而导致死锁.
>任何人都可以证实吗?
>有人可以建议修复吗?
我试过在最后的查询中调用SetLockMode(LockMode.None),但这会导致我无法弄清楚的NullReferenceException.
编辑:如果我在保存对象之前运行查询,它可以工作,但是我没有完成验证我的插入没有以某种方式超过限制(在并发插入的情况下)的目标.
编辑:我发现在session.BeginTransaction调用中使用IsolationLevel.ReadUncommited解决了问题,但我不是数据库专家.这是解决问题的适当方法,还是应该如何调整逻辑?
解决方法
在这种情况下,Read Uncommitted不是你的朋友,因为它基本上都是“忽略锁定”,这在某种程度上意味着违反了你围绕数据设置的规则. I.E.表中记录的计数将是不准确的,您将对该不准确的计数采取行动.当真实答案为11时,您的计数将返回10或13.
我最好的建议是重新排列插入逻辑,以便捕获计数的想法,而无需计算行数.你可以去几个方向.我有一个想法是这样:用插入的凭证对序列进行编号,并对序列本身强制执行限制.
>创建一个包含列的序列表(我猜)MallID,nextVoucher,maxVouchers
>使用mallid,1表示该表,以及每个商场的限制
>将插入逻辑更改为此伪代码:
Begin Transaction Sanity check the nextVoucher for Mall in the sequence table; if too many exist abort If less than MaxVouchers for Mall then { check,fetch,lock and increment nextVoucher if increment was successful then use the value of nextVoucher to perform your insert. Include it in the target table. } Error? Rollback No Error? Commit
像这样的序列表会损害并发性,但我认为并不像计算表中的行那么频繁.一定要进行性能测试.
此外,[检查,获取,锁定和增量]很重要 – 您必须排除序列表中的行,以防止某些其他连接在递增之前在分秒中使用相同的值.我知道这个的sql语法,但我担心我不是nHibernate专家.
对于读取未提交的数据错误,请查看:http://sqlblog.com/blogs/merrill_aldrich/archive/2009/07/29/transaction-isolation-dirty-reads-deadlocks-demo.aspx(免责声明:Merrill Aldrich是我:-)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。