IN SQL Server 2012 Enterprise edition, you can use AlwaysON Availability groups to achieve what you want.
If you have 2 servers set up, then you can configure AlwaysON.
Primary server will be your main and secondary (Replica) - when configured as "Readable" will allow you to redirect all "Read Intent" requests to secondary replica as well as the secondary replica is a read-only replica.
Note that, your clients are connected to the Availability Group using Listener, which allows seamless failover for your application.
In case of disaster you have all your concerns covered
A. Not have boxes sitting around doing nothing waiting for a failure.
The secondary will be used for read intent requests and will server as a standby server in case the primary fails.
B. Automatic fail over. We don't want to be running like headless chickens flipping switches and configuration settings when a database / box fails
When you use synchronous mode, it will allow you for automatic failover. In my testing, asynchronous mode (without automatic failover - manual failover) has proven more benefits in terms of performance. SO depending on the data loss allowed by your company and the downtime, you can choose between them.
AlwaysON allows you to Configure Flexible Failover Policy to Control Conditions for Automatic Failover
C. Sensible fail-over times (e.g. a five minute fail over is not sustainable)
AlwaysON will provide failover in terms of seconds, but it depends on your n/w.
EDIT :
If you implement AlwaysON (which fits in your situation), below is my recommendation:
Assuming (from your post) DB1 is the main database and DB2 is for reporting.
Configure DB1 as primary in AlwaysON. You get a warm standby database on the secondary server (say DB1_Replica).
Configure DB1_Replica as readable and have asynchronous-Commit mode configured.
Under asynchronous-commit mode, the secondary replica never becomes synchronized with the primary replica. Though a given secondary database might catch up to the corresponding primary database, any secondary database could lag behind at any point. Asynchronous-commit mode can be useful in a disaster-recovery scenario in which the primary replica and the secondary replica are separated by a significant distance and where you do not want small errors to impact the primary replica or in or situations where performance is more important than synchronized data protection. Furthermore, since the primary replica does not wait for acknowledgements from the secondary replica, problems on the secondary replica never impact the primary replica.
The listener is going to help you with seamless failover.
Refer to below links to get you started :
Do I need to make the "unlock" SERIALIZABLE
as well?
Despite the name, the serializable isolation level does not guarantee transactions will be executed sequentially, or in the order received. Rather, serializable guarantees transactions will have the same persistent effects on the database as if they had executed sequentially, in some undefined order (see the link for more details).
Are there any other approaches that I could use/anything that I have forgotten?
Yes. SQL Server already provides support for arbitrary application locks via:
These built-in applock features provide a broad range of options, and include automatic deadlock detection (though any transaction rollback required is the programmer's responsibility). For example, you can choose from transaction- and session-scoped locking, in a variety of modes. Using these features to implement the behaviour you need should be quite straightforward, and certainly simpler than building your own resilient and reliable lock manager from scratch.
Best Answer
Replication from one box to area servers, then having those area servers replicate to the store servers within that area is easy. Setting up the replication to feed from two different area servers to each store server isn't really going to be doable. You could probably hack it to work, but it wouldn't be all that easy.
You would be better off setting up the area servers with high availability so that the chance of the area server going offline in minimal.