1

I have an NHibernate MVC application that is using ReadCommitted Isolation.

On the site, there is a certain process that the user could initiate, and depending on the input, may take several minutes. This is because the session is per request and is open that entire time.

But while that runs, no other user can access the site (they can try, but their request won't go through unless the long-running thing is finished)

What's more, I also have a need to have a console app that also performs this long running function while connecting to the same database. It is causing the same issue.

I'm not sure what part of my setup is wrong, any feedback would be appreciated.

NHibernate is set up with fluent configuration and StructureMap.

  • Isolation level is set as ReadCommitted.
  • The session factory lifecycle is HybridLifeCycle (which on the web should be Session per request, but on the win console app would be ThreadLocal)
4

4 回答 4

5

It sounds like your requests are waiting on database locks. Your options are really:

  1. Break the long running process into a series of smaller transactions.
  2. Use ReadUncommitted isolation level most of the time (this is appropriate in a lot of use cases).
  3. Judicious use of Snapshot isolation level (Assuming you're using MS-SQL 2005 or later).

(N.B. I'm assuming the long-running function does a lot of reads/writes and the requests being blocked are primarily doing reads.)

于 2013-09-08T04:58:04.343 回答
3

As has been suggested, breaking your process down into multiple smaller transactions will probably be the solution.

I would suggest looking at something like Rhino Service Bus or NServiceBus (my preference is Rhino Service Bus - I find it much simpler to work with personally). What that allows you to do is separate the functionality down into small chunks, but maintain the transactional nature. Essentially with a service bus, you send a message to initiate a piece of work, the piece of work will be enlisted in a distributed transaction along with receiving the message, so if something goes wrong, the message will not just disappear, leaving your system in a potentially inconsistent state.

Depending on what you need to do, you could send an initial message to start the processing, and then after each step, send a new message to initiate the next step. This can really help to break down the transactions into much smaller pieces of work (and simplify the code). The two service buses I mentioned (there is also Mass Transit), also have things like retries built in, and error handling, so that if something goes wrong, the message ends up in an error queue and you can investigate what went wrong, hopefully fix it, and reprocess the message, thus ensuring your system remains consistent.

Of course whether this is necessary depends on the requirements of your system :)

于 2013-09-13T16:33:16.513 回答
1

Another, but more complex solution would be:

You build a background robot application which runs on one of the machines

  • this background worker robot can be receive "worker jobs" (the one initiated by the user)
  • then, the robot processes the jobs step & step in the background

Pitfalls are: - you have to programm this robot very stable - you need to watch the robot somehow

Sure, this is involves more work - on the flip side you will have the option to integrate more job-types, enabling your system to process different things in the background.

于 2013-09-13T13:05:36.937 回答
1

I think the design of your application /SQL statements has a problem , unless you are facebook I dont think any process it should take all this time , it is better to review your design and check where is the bottleneck are, instead of trying to make this long running process continue .

also some times ORM is not good for every scenario , did you try to use SP ?

于 2013-09-13T13:58:34.847 回答