Boris Barroso
Boris Barroso

Reputation: 1812

Should I use multiple databases?

I am about to create an application with Ruby on Rails and I would like to use multiple databases, basically is an accounting app that will have multiple companies for each user. I would like to create a database for each company

I found this post http://programmerassist.com/article/302 But I would like to read more thoughts about this issue. I have to decide between MySQL and PosgreSQL, which database might fit better my problem.

Upvotes: 3

Views: 2396

Answers (4)

Boris Barroso
Boris Barroso

Reputation: 1812

It has past time and the decission for this has been to use PostgreSQL schemas, making multitenant applications, I have a schema called common where related data is stored.

# app/models/organisation.rb
class Organisation < ActiveRecord::Base
  self.table_name = 'common.organisations'
  # set relationships as usual
end

# app/models/user.rb    
class User < ActiveRecord::Base
  self.table_name = 'common.users'
  # set relationships as usual
end

Then for migrations I have done that with this excellent tutorial. http://timnew.github.com/blog/2012/07/17/use-postgres-multiple-schema-database-in-rails/ use this, this is way better than what I saw in other places even the way Ryan Bates did on railscasts.

When a new organisation is created then a new schema is created with the name of the subdomain the organisation. I have read in the past that it's not a good idea to use different schemas but it depends on the job you are doing, this app has almost no soccial component so it's a good fit.

Upvotes: 0

Greg Wallace
Greg Wallace

Reputation: 11

The problem with answers about multiple databases is when they come from people who don't have a need or experience with multiple databases. The second problem is that some databases just don't allow for switching between multiple databases, including allowing users to do their own backup and recovery and including scaling to point some users to a different data server. Here is a link to a useful video http://aac2009.confreaks.com/06-feb-2009-14-30-writing-multi-tenant-applications-in-rails-guy-naor.html

This link will help with Ruby on Rails with Postgresql.

I currently have a multi-tenant, multi-database, multi-user (many logons to the same tenant with different levels of access), and being an online SaaS application. There are actually two applications one is in the accounting category and the other is banking. Both Apps are built on the same structure and methods. A client-user (tenant) can switch databases under that user's logon. An agent-user such as a tax accountant can switch between databases for his clients only. A super-user can switch to any database. There is one data dictionary i.e. only one place where tables and columns are defined. There is global data and local data. Global data such as a master chart-of-accounts which is available to everyone (read only). Local data is the user's database. A new user can get a clone of a master database. There are multiple clones to choose from. A super-user can maintain the clone databases.

The problem is that it is in COBOL and uses ISAM files and uses the CGI method. The problem with this is a) there is a perception that COBOL is outdated, b) getting trained people, c) price and d) online help. Otherwise it works and I'm happy with it.

So I'm researching what to replace it with and what a minefield that is.

Upvotes: 1

Toby Hede
Toby Hede

Reputation: 37143

There are several options for handling a multi-tenant app.

Firstly, you can add a scope to your tables (as suggested by Chad Birch - using a company_id). For most use-cases this is fine. If you are handling data that is secure/private (such as accounting information) you need to be very careful about your testing to ensure data remains private.

You can run your system using multiple databases. You can have a single app that uses a database for each client, or you can have actually have a seperate app for each client. Running a database for each client cuts a little against the grain in rails, but it is doable. Depending on the number of clients you have, and the load expectations, I would actually suggest having a look at running individual apps. With some work on your deployment setup (capistrano, chef, puppet, etc) you can make this a very streamlined process. Each client runs in a completely unique environment, and if a particular client has high loads you can spin them out to their own server.

If using PostgreSQL, you can do something similar using schemas. PostgresQL schemas provide a very handy way of islolating your data from different clients. A database contains one or more named schemas, which in turn contain tables. You need to add some smarts to your migrations and deployments, but it works really well.

Inside your Rails application, you attach filters to the request that switch the current user's schema on or off.

Something like:

before_filter :set_app

def set_app
  current_app = App.find_by_subdomain(...)
  schema = current_app.schema

  set_schema_path(schema)
end 


def set_schema_path(schema)
  connection = ActiveRecord::Base.connection
  connection.execute("SET search_path TO #{schema}, #{connection.schema_search_path}")
end

def  reset_schema_path
  connection = ActiveRecord::Base.connection
  connection.execute("SET search_path TO #{connection.schema_search_path}")
end

Upvotes: 6

Chad Birch
Chad Birch

Reputation: 74648

No, you shouldn't use multiple databases.

I'm not really sure what advice to give you though, it seems like you have some very basic misunderstandings about database design, you may want to educate yourself on the basics of databases first, before going further.

You most likely just want to add a "company id" type column to your tables to identify which company a particular record belongs to.

Upvotes: -1

Related Questions