Как спроектировать многопользовательскую базу данных MySQL - PullRequest
26 голосов
/ 06 апреля 2011

Допустим, мне нужно спроектировать базу данных, в которой будут размещаться данные для нескольких компаний. Теперь в целях безопасности и администрирования мне нужно убедиться, что данные для разных компаний должным образом изолированы, но я также не хочу запускать 10 процессов mysql для размещения данных для 10 компаний на 10 разных серверах. Каковы наилучшие способы сделать это с базой данных mysql.

Ответы [ 6 ]

30 голосов
/ 07 апреля 2011

Существует несколько подходов к мультитенантным базам данных. Для обсуждения их обычно разбивают на три категории.

  • Одна база данных на каждого арендатора.
  • Общая база данных, одна схема на арендатор.
  • Общая база данных, общая схема. Идентификатор арендатора (ключ арендатора) связывает каждую строку с нужным арендатором.

В MSDN есть хорошая статья о плюсах и минусах каждого проекта и примерах реализации .


Microsoft, очевидно, удалила страницы, на которые я ссылался, но они есть на archive.org. Ссылки были изменены, чтобы указать там.

Для справки, это оригинальная ссылка для второй статьи

5 голосов
/ 12 ноября 2011

Простой способ: для каждой разделяемой таблицы добавьте столбец с именем SEGMENT_ID.Назначенный правильный SEGMENT_ID для каждого клиента.Затем создайте представления для каждой клиентской базы по SEGMENT_ID. Эти представления будут хранить данные отдельно от каждого клиента.С помощью этого метода можно обмениваться информацией, что упрощает как эксплуатацию, так и разработку (хранимая процедура также может быть предоставлена) просто.

3 голосов
/ 06 апреля 2011

Предполагая, что вы запустите одну базу данных MySQL на одном экземпляре MySQL - есть несколько способов, как отличить то, кому принадлежит.Наиболее очевидным выбором (по крайней мере для меня) будет создание составного первичного ключа, такого как:

CREATE TABLE some_table (
id int unsigned not null auto_increment,
companyId int unsigned not null,
..
..
..,
primary key(id, company_id)
) engine = innodb;

, а затем различие между компаниями путем изменения идентификатора компании в первичном ключе.Таким образом, вы можете иметь все данные всех компаний в одной таблице / базе данных, а на уровне приложения вы можете контролировать, какая компания связана с какой идентификатором компании, и определить, какие данные отображать для определенной компании.

Если этоне то, что вы искали - мои извинения за неправильное понимание вашего вопроса.

1 голос
/ 23 августа 2018

В MySQL я предпочитаю использовать одну базу данных для всех арендаторов. Я ограничиваю доступ к данным, используя отдельного пользователя базы данных для каждого арендатора, который имеет доступ только к представлениям, которые показывают только строки, принадлежащие этому арендатору.

Это может быть сделано:

  1. Добавить столбец tenant_id к каждой таблице
  2. Используйте триггер, чтобы заполнить tenant_id текущим именем пользователя базы данных при вставке
  3. Создать представление для каждой таблицы, где tenant_id = current_database_username
  4. Используйте только представления в вашем приложении
  5. Подключиться к базе данных, используя имя пользователя для конкретного арендатора

Я полностью задокументировал это в сообщении в блоге: https://opensource.io/it/mysql-multi-tenant/

1 голос
/ 06 апреля 2011

Рассматривали ли вы создание отдельной схемы для каждой компании?

Вы должны попытаться более точно определить, чего вы хотите достичь.

Если вы хотите убедиться, что сбой HW не ставит под угрозу данные для более чем одной компании, напримервам нужно создавать разные экземпляры и запускать их на разных узлах.

Если вы хотите убедиться, что кто-то из компании A не может видеть данные, принадлежащие компании B, вы можете сделать это на уровне приложения, как сказал МатфейОтвет ПК, например,

Если вы хотите быть уверены, что кому-то, кому удастся скомпрометировать безопасность и запустить произвольный SQL-запрос к БД, вам нужно что-то более надежное, чем это.Вы хотите иметь возможность создавать резервные копии данных независимо друг от друга, чтобы вы могли безопасно создавать резервные копии данных о компании C по понедельникам и компании A по воскресеньям и иметь возможность восстанавливать только компанию C, тогда опять решение на основе приложений не поможет.

1 голос
/ 06 апреля 2011

Для конкретного пользователя БД вы можете предоставить членство в группах, указав компании, к которым им разрешен доступ.

Я предполагаю, что у вас будет таблица Companies, поэтому просто создайте отношения один-ко-многим между Companies и MySQLUsers или что-то подобное.

Затем, в качестве условия всех ваших запросов, просто сопоставьте CompanyID на основе UserID

...