<?xml version="1.0" encoding="UTF-8"?><rss
version="2.0"
xmlns:content="http://purl.org/rss/1.0/modules/content/"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:atom="http://www.w3.org/2005/Atom"
xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
> <channel><title>Comments on: Is This A Good Approach For Multi-Tenancy Or Not?</title> <atom:link href="http://davybrion.com/blog/2008/12/is-this-a-good-approach-for-multi-tenancy-or-not/feed/" rel="self" type="application/rss+xml" /><link>http://davybrion.com/blog/2008/12/is-this-a-good-approach-for-multi-tenancy-or-not/</link> <description>inquisitive: adjective. given to inquiry, research, or asking questions; eager for knowledge; intellectually curious</description> <lastBuildDate>Sun, 20 May 2012 21:55:00 +0000</lastBuildDate> <sy:updatePeriod>hourly</sy:updatePeriod> <sy:updateFrequency>1</sy:updateFrequency> <generator>http://wordpress.org/?v=3.3.2</generator> <item><title>By: Rohland de Charmoy</title><link>http://davybrion.com/blog/2008/12/is-this-a-good-approach-for-multi-tenancy-or-not/comment-page-1/#comment-7590</link> <dc:creator>Rohland de Charmoy</dc:creator> <pubDate>Mon, 12 Jan 2009 14:05:30 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/?p=730#comment-7590</guid> <description>HiI have been involved in a few applications that require this type of architecture. For the database I would suggest the following (I am assuming you are using SQL Server):1. Create only one instance of the database with all the customers data (see below for more information regarding partitioning).
2. Add an account column to each table (you can do this with script) with a default value of suser_sname() (This function returns the name of the currently logged in user, basically you are implementing row-level security)
3. For each customer, create a separate login to SQL Server
4. Create a view for every table that looks like this:SELECT col1, col2, col3 FROM mytable WHERE account = suser_sname()5. Update your DAL to query the views and not the tables. Inserts, updates, deletes will still work.
6. Develop some code so that when a user logs in, it checks what their associated customer login is, subsequent database calls should be made with this login.This works really well. In terms of maintenance, you only ever work with one database. If you are fixing a bug or checking out an issue for Customer B, you can log into the database with customer B&#039;s associated login. If you run a query that looks like this &quot;DELETE FROM vw_mytable&quot; you will only every affect Customer B as the views have effectively partitioned your context. I would suggest adding each customer&#039;s account to a database role which only allows inserts, update, deletes for the relevant views (ensures you haven&#039;t missed a table).Hope this helps.
Rohland</description> <content:encoded><![CDATA[<p>Hi</p><p>I have been involved in a few applications that require this type of architecture. For the database I would suggest the following (I am assuming you are using SQL Server):</p><p>1. Create only one instance of the database with all the customers data (see below for more information regarding partitioning).<br
/> 2. Add an account column to each table (you can do this with script) with a default value of suser_sname() (This function returns the name of the currently logged in user, basically you are implementing row-level security)<br
/> 3. For each customer, create a separate login to SQL Server<br
/> 4. Create a view for every table that looks like this:</p><p>SELECT col1, col2, col3 FROM mytable WHERE account = suser_sname()</p><p>5. Update your DAL to query the views and not the tables. Inserts, updates, deletes will still work.<br
/> 6. Develop some code so that when a user logs in, it checks what their associated customer login is, subsequent database calls should be made with this login.</p><p>This works really well. In terms of maintenance, you only ever work with one database. If you are fixing a bug or checking out an issue for Customer B, you can log into the database with customer B&#8217;s associated login. If you run a query that looks like this &#8220;DELETE FROM vw_mytable&#8221; you will only every affect Customer B as the views have effectively partitioned your context. I would suggest adding each customer&#8217;s account to a database role which only allows inserts, update, deletes for the relevant views (ensures you haven&#8217;t missed a table).</p><p>Hope this helps.<br
/> Rohland</p> ]]></content:encoded> </item> <item><title>By: Mai Kalange</title><link>http://davybrion.com/blog/2008/12/is-this-a-good-approach-for-multi-tenancy-or-not/comment-page-1/#comment-6636</link> <dc:creator>Mai Kalange</dc:creator> <pubDate>Fri, 19 Dec 2008 11:50:35 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/?p=730#comment-6636</guid> <description>Sounds familiar to a problem that we had to solve only that we did not have the benefit of NHibernate.
What we did have was a single DB instance, the Enterprise Caching Block and DAAB. Yes the good old days ;)The application had to service different mobile network operators&#039;(the tenants) devices as part of the initial phone configuration workflow. Each tenant had a contract definition which included handsets that they supported, associated device settings(as xml documents).Access to the application was via the following mechanismconfiguration.service.com?contractId=00000000239. This triggered a FrontController that went about initialising the session and loaded core data in the cache and keyed it by contractId, peripheral data was lazy loaded.</description> <content:encoded><![CDATA[<p>Sounds familiar to a problem that we had to solve only that we did not have the benefit of NHibernate.<br
/> What we did have was a single DB instance, the Enterprise Caching Block and DAAB. Yes the good old days <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /></p><p>The application had to service different mobile network operators&#8217;(the tenants) devices as part of the initial phone configuration workflow. Each tenant had a contract definition which included handsets that they supported, associated device settings(as xml documents).</p><p>Access to the application was via the following mechanism</p><p>configuration.service.com?contractId=00000000239. This triggered a FrontController that went about initialising the session and loaded core data in the cache and keyed it by contractId, peripheral data was lazy loaded.</p> ]]></content:encoded> </item> <item><title>By: Ayende Rahien</title><link>http://davybrion.com/blog/2008/12/is-this-a-good-approach-for-multi-tenancy-or-not/comment-page-1/#comment-6570</link> <dc:creator>Ayende Rahien</dc:creator> <pubDate>Thu, 18 Dec 2008 01:45:03 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/?p=730#comment-6570</guid> <description>All databases having the same scheme - Take care of problematic versioning in this scenario. You are likely to run into situations where you cannot change the system all at once.tenantb.ourproduct.com - that is the most common way to do that, the other way of doing that is to have a common login page and redirect base on the user object (shared across all tenants).
The 2nd Level Cache is great, but it doesn’t differentiate between multiple SessionFactories. - not quite accurate, you can define regions, and IIRC, it uses the session factory name as part of the cache space.
I wouldn&#039;t go with the virtual dir path, myself.</description> <content:encoded><![CDATA[<p>All databases having the same scheme &#8211; Take care of problematic versioning in this scenario. You are likely to run into situations where you cannot change the system all at once.</p><p>tenantb.ourproduct.com &#8211; that is the most common way to do that, the other way of doing that is to have a common login page and redirect base on the user object (shared across all tenants).<br
/> The 2nd Level Cache is great, but it doesn’t differentiate between multiple SessionFactories. &#8211; not quite accurate, you can define regions, and IIRC, it uses the session factory name as part of the cache space.<br
/> I wouldn&#8217;t go with the virtual dir path, myself.</p> ]]></content:encoded> </item> <item><title>By: Jeremy Gray</title><link>http://davybrion.com/blog/2008/12/is-this-a-good-approach-for-multi-tenancy-or-not/comment-page-1/#comment-6564</link> <dc:creator>Jeremy Gray</dc:creator> <pubDate>Wed, 17 Dec 2008 23:41:23 +0000</pubDate> <guid
isPermaLink="false">http://davybrion.com/blog/?p=730#comment-6564</guid> <description>&quot;we’ve decided to go with a separate database for each tenant&quot;Then you aren&#039;t doing multi-tenanting, at least in that most if not all descriptions of multi-tenanting that I have encountered have required that multi-tenanting be taking place within a database instance (as doing multi-tenanting up at the web tier is the easy part regardless of how the database instances are set up.)&quot;Each database will have an identical structure&quot;Good call. Each and every time I&#039;ve seen people go down the path of having different schema per instance it has become a very large headache.&quot;Our first idea was to have one actual instance of the application&quot;Also a good call in general, but make sure to at least consider being able to configure your load-balancing so as to focus a given client&#039;s users on a given subset of servers so as to maximize web tier in-memory cache coherency and to keep from overrunning your database servers&#039; ability to accept incoming connections for each schema instance. You&#039;re going to need to monitor, analyze, and adjust a number of balancing factors between things like the number of web servers and the number of database servers, clients per web server, maximum db connections per web-server-client-instance, the number of db schema instances per physical db server, etc.&quot;We still have the benefit of one physical deployment, and because each tenant’s ‘virtual’ application runs in its own AppDomain, the caching problem is no longer an issue.&quot;But memory usage will then be an issue. This will in turn push you towards installing components in the GAC so as to get shared code in memory. This in turn will push you towards having to deal with annoying component deployment and versioning issues. I&#039;m not going to suggest that this is a horrible route, or that the alternatives are perfect, but do be aware that there be dragons down the path of separation by AppDomain. :)Jeremy</description> <content:encoded><![CDATA[<p>&#8220;we’ve decided to go with a separate database for each tenant&#8221;</p><p>Then you aren&#8217;t doing multi-tenanting, at least in that most if not all descriptions of multi-tenanting that I have encountered have required that multi-tenanting be taking place within a database instance (as doing multi-tenanting up at the web tier is the easy part regardless of how the database instances are set up.)</p><p>&#8220;Each database will have an identical structure&#8221;</p><p>Good call. Each and every time I&#8217;ve seen people go down the path of having different schema per instance it has become a very large headache.</p><p>&#8220;Our first idea was to have one actual instance of the application&#8221;</p><p>Also a good call in general, but make sure to at least consider being able to configure your load-balancing so as to focus a given client&#8217;s users on a given subset of servers so as to maximize web tier in-memory cache coherency and to keep from overrunning your database servers&#8217; ability to accept incoming connections for each schema instance. You&#8217;re going to need to monitor, analyze, and adjust a number of balancing factors between things like the number of web servers and the number of database servers, clients per web server, maximum db connections per web-server-client-instance, the number of db schema instances per physical db server, etc.</p><p>&#8220;We still have the benefit of one physical deployment, and because each tenant’s ‘virtual’ application runs in its own AppDomain, the caching problem is no longer an issue.&#8221;</p><p>But memory usage will then be an issue. This will in turn push you towards installing components in the GAC so as to get shared code in memory. This in turn will push you towards having to deal with annoying component deployment and versioning issues. I&#8217;m not going to suggest that this is a horrible route, or that the alternatives are perfect, but do be aware that there be dragons down the path of separation by AppDomain. <img
src='http://d18sni7re4ly7f.cloudfront.net/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p><p>Jeremy</p> ]]></content:encoded> </item> </channel> </rss>
<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using disk: basic
Page Caching using disk: enhanced
Database Caching 2/8 queries in 0.003 seconds using disk: basic
Object Caching 376/377 objects using disk: basic
Content Delivery Network via Amazon Web Services: CloudFront: d18sni7re4ly7f.cloudfront.net

Served from: davybrion.com @ 2012-05-21 14:03:05 -->
