Ответы пользователя по тегу MySQL
  • Правильная ли декомпозиция базы данных?

    В целом, у вас всё достаточно просто. Я предложу вам вариант схемы, а вы сравните его со своей.
    Попытаемся рассуждать в терминах множеств - это всегда полезно при проектировании реляционных БД, т.к. отношения - это множества.

    Итак, у вас есть множество мест, доступных для бронирования. Будем считать, что БД обслуживает только ОДИН стадион. Сектор, ряд и номер места - это всё иерархические координаты места, однозначно это место определяющие. Таким образом, ключом для места является (sector, row, number).

    Далее нам нужно решить, как мы будем представлять множество ВСЕХ мест. Вы указали, что количество мест известно заранее. По идее, в этом случае нам даже не нужно хранить множество этих мест, т.к. оно определяется правилом, однако рано или поздно вы столкнётесь с тем, что правило необходимо нарушить - например, какое-то из мест в данный момент оказалось непригодным для продажи билетов (сломали стул, отвалился порог, и т.д.). Поэтому ИМХО стоит всё-таки завести отношение "Место" для хранения множества ВСЕХ имеющихся мест, как вы собственно и сделали. Т.е. мы имеем первое отношение: Seat(sector, row, number).

    Теперь мы хотим хранить множество забронированных мест. Т.к. событий на стадионе будет много, для каждого из событий мы будем иметь своё множество забронированных мест. Значит, в первичный ключ отношения "забронированное место" должен попасть первичный ключ события. Предположим, что первичный ключ события это id (т.к. других подробностей вы не указали). Остальные атрибуты отношения "забронированное место" должны ссылаться на одно из имеющихся мест, т.е. у нас должен быть внешний ключ в отношение "Место" (Seat). Итак, мы имеем второе отношение: ReservedSeat(event_id, sector, row, number). При проектировании реляционной БД очень важно четко понимать, что значит НАЛИЧИЕ или ОТСУТСТВИЕ записи в каждом из отношений. Наличие записи в отношении ReservedSeat говорит нам, что конкретное место забронировано на конкретное событие. Ни больше, ни меньше. Если некоторой записи в отношении ReservedSeat нет, значит конкретное место на конкретное событие все еще свободно.
    И да, кажется мы забыли главное - а кем место-то занято? Нам нужен еще один атрибут, внешний ключ в отношение User. Добавим его:
    ReservedSeat(event_id, sector, row, number, user_id)
    . Важно, что этот атрибут не входит в первичный ключ, т.к. разные клиенты не могут забронировать одно и то же место (т.е. место всегда бронируется кем-то одним).

    Собственно, всё. Отношение User переписываем как есть, т.к. вы не указали подробностей о том, что там хранить. Отношение Event я придумаю "с потолка", добавив туда только атрибут name помимо ключа id.

    Итого (атрибуты, входящие в первичный ключ, выделены жирным):
    User(id, name, surname);
    Seat(sector, row, number);
    Event(id, name);
    ReservedSeat(event_id, sector, row, number, user_id); внешние ключи: event_id -> Event(id), user_id -> User(id); (sector, row, number) -> Seat(sector, row, number).

    Надеюсь, процесс принятия решений описан достаточно понятно. Если остались вопросы - задавайте.
    Ответ написан
    5 комментариев
  • Какие аргументы в пользу использования транзакций в бд?

    И тут выясняется, что ребята совсем нигде(!) не используют транзакций при записи связанных данных. И внешних ключей нигде(!!) в бд не ставят.

    Либо какие-то просветленные, либо дети NoSQL-эры. Скорее всего второе.

    На мои аргументы, что это угрожает целостности данных отвечают, что целостность должна контролироваться на уровне кода самого приложения.

    Да, должна контроллироваться на уровне приложения. Но в большинстве случаев это не повод отказываться от внешний ключей и прочих средств контроля целостности. Да, я видел, что некоторые вендоры НЕ используют ограничения целостности в релизных версиях продуктов, но это скорее исключение, чем правило. И да, самое главное - в большинстве случаев данные живут дольше, чем приложение, с ними работающее. Или - также не редкость - приложений, работающий с одной базой - несколько. Тогда вам рано или поздно захочется дополнительный уровень "доверия", т.е. контроля целостности. Вы должны понимать, что неконсистентные данные в базе - это как правило большой или очень большой гемор, т.к. после появления таких данных в базе очень непросто понять, что они там делают, и что ВАМ теперь с ними делать.
    Ограничения целостности снимают только если они заметно снижают производительность БД, её (производительности) не хватает, других способов быстро поправить ситуацию нет, и у вас на данный момент уже есть хоть какая-то уверенность, что приложение не накосячит в БД.

    А теперь последнее. Целостность данных - не единственное, и даже не главное, для чего нужны и полезны транзакции. Дмитрий Энтелис классно написал про профнепригодность: попросите своих коллег написать биллинг кому-нибудь, выкатить его в продакшн, а потом объяснить начальнику отдела и директору, почему у некоторых клиентов, купивших две услуги по 500, списалось только за одну услугу. Можете рассказать коллегам про уровни изоляции - тут кстати навалом примеров.
    Ответ написан
    2 комментария
  • Как правильно создать архитектуру БД для нескольких сервисов?

    Если бы в тегах у вас не стоял MySQL, я бы сказал - "используйте схемы". В нормальных СУБД "база данных" - это единица администрирования, а "схема" - это пространство имён, т.е. как раз то, что вам нужно для различных сервисов и подсистем.

    Судя по тому, что вы описали, сервисов у вас несколько, но предметная область одна и та же, верно? т.е. эти сервисы всё-таки связаны, и возможно (даже вероятно) вам пригодятся связи между таблицами разных сервисов. И тут я бы тоже вам сказал "используйте схемы".

    В разных БД желательно хранить абсолютно несвязанные данные, такие, что можно взять одну из БД и спокойно перекинуть на другой сервер, или вообще на другую СУБД. Например, в одной БД у вас CRM-система, а в другой хранит данные ваш почтовый сервер. А в третьей данные для промо-сайта.

    Но т.к. вы указали MySQL, я говорю вам "используйте префикс к таблицам".

    К ответу Александр : как раз таки если это всё сервисы одного предприятия, то и авторизация лучше будет отдельным сервисом, наравне с остальными. Также со своей схемой/префиксом.
    Ответ написан
    Комментировать
  • Как обрабатывать параллельные запросы к Интернет-магазину?

    Что будет, если к базе данных подключатся два посетителя?

    Если СУБД подразумевает многопользовательскую обработку данных (MySQL в их числе), то все будет в порядке. Более того, современные клиент-серверные СУБД для того и нужны, чтобы к ним могли подключаться множество клиентских приложений и отправлять запросы. Сотни и тысячи подключений - нормальная ситуация для загруженного сайта.
    Могут ли PHP-сценарии выполнятся параллельно?

    Разумеется, иначе как получить приемлемую отзывчивость для сайта?
    Можно ли к БД подключиться параллельно, используя одного и того же пользователя БД?

    Вообще это зависит от СУБД, иногда можно ограничивать количество TCP-подключений для одного БД-пользователя. Но как правило по-умолчанию это ограничение не стоит, и обычно все запущенные экземпляры скрипта используют одного юзера для подключения. Иногда для разных скриптов используют разных пользователей БД в целях повышения безопасности - например, для обычных посетителей - пользователя с меньшим набором прав, а для администратора или менеджера - другого пользователя с полным доступом к БД. Тогда, в случае эксплуатируемой SQL-инъекции последствия будут не такими значительными. [В такой архитектуре обычно каждый пользователь БД соответствует одной роли в приложении (администратор/контент-менеджер/обычный посетитель)].

    Если к базе данных могут происходить параллельные подключения, как синхронизировать доступ?

    Или транзакции с определённым уровнем блокировки?

    Не знаю, что вы понимаете под "уровнем блокировки", но вам определенно следует познакомиться с уровнями изолированности транзакций.
    Например, читатели (посетители) просматривают товары, а писатель (администратор) обновляет цены или добавляет новый товар.

    Если разберетесь с уровнями изолированности - получите ответы на такие вопросы. В частности, read commited (уровень изоляции по умолчанию в большинстве реляционных СУБД) как раз решит проблему параллельных чтения и обновления.

    Вообще, с транзакциями определенно следует познакомиться, тем более раз уж взяли в качестве учебного задания интернет-магазин. Только в этом случае можно считать этот учебный проект завершенным.
    Ответ написан
    Комментировать
  • Как лучше хранить в MySQL временную зону?

    Красивое решение будет тогда, когда вы точно определитесь, что вам надо хранить. Если условия задачи говорят, что нужно хранить по одной зоне на каждое смещение относительно UTC - это одно. Тогда можно хранить только смещение относительно UTC (не вижу проблемы с отрицательными, учтите только, что не все смещения кратны одному часу). Чтобы красиво смотреть глазами, нужно завести отдельную таблицу с названиями таймзон и джойнить с ней, чтобы посмотреть.
    Если вам нужна таймзона в каждом городе - это совсем другая история. Или в каждой точке планеты с целым значением широты и долготы.
    Если вы хотите 1-в-1 взять с Википедии, прилепите суррогатный id к тому что там написано, и пользуйтесь.
    Ответ написан
    Комментировать
  • Есть ли генератор SQL кода на C++ сразу под несколько БД (MySQL, SQLite, MS SQL)?

    Nipheris
    @Nipheris Куратор тега C++
    Библиотеку для абстрагирования работы с разными СУБД могу посоветовать такую: https://github.com/SOCI/soci , только это не ORM, а именно абстракция от конкретной СУБД и конкретной клиентской библиотеки. Вообще под плюсами ORM не особо живут и плодятся ввиду принципиального отсутствия рефлексии в языке. Какие-то были на базе Qt (MOC как раз и обеспечивает для них наличие мета-объектов), но они слабо развиваются.

    Советую еще раз поразмыслить над необходимостью именно генерировать SQL-запросы - возможно вам стоит писать их самому (тем более раз у вас действия простые), а вот абстракция от СУБД как раз бы пригодилась вам.
    Я конечно не знаю, что у вас за проект, но раз вы используете плюсы, то у вас либо какой-то сервис с низким содержанием бизнес-логики (например, принимающий данные от устройств и пишущий базу), либо иное обслуживающее ПО, в которых обычно не очень много SQL-запросов.
    Ответ написан
  • В чём смысл поля binary?

    И в дополнение ещё вопросик: в каком типе поля лучше хранить md5-хэш (с индексом по нему)?

    BINARY(16). VAR не нужен, т.к. длина хэша постоянна, строка фиксированного размера будет работать намного веселее. В CHAR не вижу смысла - хэш по сути есть последовательность байт, ну или если хотите - большое число. Хранить его hex-строкой считаю странной практикой. В базе посмотреть удобно, больше преимуществ не вижу.

    P.S. Не забывайте, что голый MD5 давно не считается безопасным.
    Ответ написан
  • Как именно плейсхолдеры (подготовленные выражения) защищают от sql-инъекций?

    Подготовленные выражения защищают от SQL-инъекций тем, что отделяют синтаксис запроса от значений параметров запроса. Суть любой SQL-инъекции - изменить синтаксис (текст, если угодно) запроса тем или иным образом. Если вы передаете текст запроса и параметры отдельно, не будет никакой возможности повлиять на синтаксис запроса из параметра запроса.

    В случае поддержки со стороны СУБД, подтоговленные выражения PHP должны использовать возможности СУБД и передавать ей сначала текст запроса для компиляции, а уже потом, отдельно - параметры запроса.

    Теоретически, проблемы могут быть только в случае, если prepared statements не поддерживаются самой СУБД и эмулируются PDO (т.е. на стороне скрипта, а не БД). Тогда косяки в реализации сборки конечного запроса могут сказаться на безопасности. В случае поддержки со стороны СУБД "реализовывать" просто напросто нечего - вы защищены от инъекций не за счет экранирования всего и вся, а за счет правильного подхода - никогда не смешивать сам запрос и его параметры.

    Насколько мне известно, mysql уже давным-давно поддерживает prepared statements, поэтому не вижу смысла бояться их использовать. А даже если б это было не так, вероятность в том, что при ручной сборке запроса накосячите ВЫ - гораздо выше.

    UPDATE: полезнейший коммент на странице php.net/manual/ru/pdo.prepare.php:
    With PDO_MYSQL you need to remember about the PDO::ATTR_EMULATE_PREPARES option.

    The default value is TRUE, like
    $dbh->setAttribute(PDO::ATTR_EMULATE_PREPARES,true);

    This means that no prepared statement is created with $dbh->prepare() call. With exec() call PDO replaces the placeholders with values itself and sends MySQL a generic query string.

    The first consequence is that the call $dbh->prepare('garbage');
    reports no error. You will get an SQL error during the $dbh->exec() call.
    The second one is the SQL injection risk in special cases, like using a placeholder for the table name.

    The reason for emulation is a poor performance of MySQL with prepared statements. Emulation works significantly faster.

    Так что да, есть доля внезапности в поведении PDO. Я думаю стоит порыть инфы о настройке PDO::ATTR_EMULATE_PREPARES. Я считаю, что включать по-дефолту именно эмуляцию - это в высшей степени недальновидное решение. Проблемы MySQL затыкаются на стороне стандартной библиотеки языка....
    Ответ написан
    2 комментария
  • Удобный способ вывода информации из MySQL?

    Почитайте, что такое веб-сервис, и в частности - REST-сервис, или REST API. Почитайте про то, как с помощью JSON можно обмениваться данными между веб-сервисом (т.е. бэкендом) и веб-клиентом (в том числе фронтендом в браузере).
    Сейчас для вас это другое измерение, если вы задаете такой вопрос.
    Ответ написан
    Комментировать
  • Как правильно называть связующие таблицы в схеме "Многие ко многим"?

    https://en.wikipedia.org/wiki/Associative_entity

    Можно у Дейта глянуть. По-английски называется "junction table" и еще с десяток вариаций. Вам именно русскоязычный термин нужен?
    Ответ написан
    Комментировать
  • Почему MySQL не верно сортирует при условии + группировке?

    Я может чего путаю - но вам тут GROUP BY вообще зачем? Где агрегирующее выражение? Что значит "сгруппировать по беседе"? Может вам нужна сортировка одновременно по дате и беседе?

    Необходимо вывести список бесед (а вернее последнее сообщение из каждой беседы). Беседа обозначена через thread_id. По этой самой причине идет группировка по беседе и сортировка по дате.


    Теперь понятно, попробуйте так:
    select thread_id, body, date from
    		(select message.thread_id, max(message.date) as date from message where device_id = 12 group by thread_id) as last_message
    	join
    		message
    	on message.thread_id = last_message.thread_id and message.date = last_message.date
    limit 0, 50
    Ответ написан
  • Как разобратся с внешними ключами мускул?

    А вам надо по-другому? У вас есть залогиненый юзер, вы где-то держите его id. Теперь, когда залогиненный юзер оформляет заказ, вы добавляете новый заказ этому юзеру, указывая конкретный user_id при insert-е записи в таблицу заказов.
    Смысл внешнего ключа в том, что СУБД не позволит вам добавить заказ на несуществующего юзера. Т.е. при insert-е автоматически произойдет проверка, что в родительской таблице юзеров есть запись с таким id, который вы указали в добавляемом заказе.
    Вы можете делать такой insert и без внешнего ключа, вам вообще не обязательно пользоваться внешними ключами - все равно все нужные выборки вы будете делать сами. Внешние ключи это лишь один из видов ограничений целостности, грубо говоря доп. проверка со стороны СУБД, чтобы вы могли чувствовать себя спокойнее за согласованность базы (вам же не очень хочется, чтобы в случае какой-либо досадной ошибки в приложении у вас добавился "висячий" заказ вообще непонятно на кого). Ну и еще они позволяет выполнять некоторые каскадные операции, например удалить все заказы при удалении юзера - если конечно вы так позволите делать.
    Ответ написан
    1 комментарий
  • Как лучше организовать схему бд?

    Вопрос наполовину не понял, у вас с терминологией тяжеловато.

    Мое предложение:
    - таблица Магазин(id, ...);
    - таблица Товар(id, ...);
    - таблица ЦенаТовара(id_магазина, id_товара, цена);
    Ответ написан
    1 комментарий
  • Как побороть foreign key constraint violation в MySQL?

    dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key...

    If ON UPDATE CASCADE or ON UPDATE SET NULL recurses to update the same table it has previously updated during the cascade, it acts like RESTRICT. This means that you cannot use self-referential ON UPDATE CASCADE or ON UPDATE SET NULL operations. This is to prevent infinite loops resulting from cascaded updates.


    Не имейте привычки рассчитывать на ограничения и их поведение при разработке приложения. Обновите все ключи сами - и в дочерней, и в родительской записи.
    Ответ написан
    Комментировать
  • User Settings Database Design/Scheme?

    0 [вступление] )
    Я не знаю почему но мне найблоьше нравится 3 вариант, но уже надоело делать под себя. хочется сделать как у людей)

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

    Теперь по делу:
    1) вариант подходящий для случая до 5-6 настроек на юзера, и с уверенностью, что их количество расти не будет; если больше - не стоит;
    2) это EAV. Не особо вижу в нем смысле, если вам доступен пункт 3;
    3) json-колонка settings вполне себе ничего. Важным премуществом является то, что вы тогда можете хранить только переопределенные пользователем значения. А как правило, пользователи не меняют более 20% настроек, особенно если они удачно подобраны. Т.е. после создания у вас будет пустой объект json, и после каждой смены настройки в объект будет добавляться поле, если настройка еще не менялась, либо обновляться, либо удаляться, если юзер нажал "reset to defaults". В случае пункта 1 вам бы пришлось использовать NULL для пометки того, что пользователь не устанавливал эту настройку;
    4) не вижу особого смысла: файлы настроек, вероятно, будут небольшими, плюс эти файлы будут лежать у вас списком, а не иерархией, а тогда смысл использовать ФС;

    и еще 5) если проект большой и настроек и юзеров много, я бы подумал об использовании документной БД для этой цели - тогда можно будет выделить отдельный сервис для задачи хранения настроек.
    Ответ написан
  • ADO.NET море проблем?

    Nipheris
    @Nipheris Куратор тега C#
    1) использовать EF7 с edmx невозможно, т.к. последний считается устаревшим форматом/подходом к хранению структуры БД (см. blogs.msdn.com/b/adonet/archive/2014/10/21/ef7-wha... Если все-таки очень хочется edmx - попробуйте установить EF6;
    2)
    что надо установить SQl Server

    установить надо было скорее всего Entity Framework Tools, что, в общем-то, логично. Для установки EFTools нужно при установке выбрать SQL Server Data Tools (см. https://github.com/aspnet/Tooling/issues/53 ), что тоже логично. Вы точно устанавливали их при установки студии? Обращаю ваше внимание, что это Tools, а не сервер.
    Ответ написан
    2 комментария
  • Объясните по-простому суть индексов в MySQL?

    - Анжела, где в нашей библиотеке искать посты с типом 15, статусом "опубликовано" от 13 марта 2015 года? А то читатели спрашивают, а перебирать все подряд я буду до конца следующей недели.
    - Без проблем, Вероника, сейчас скажу (заглядывает в индекс). Так, опубликованные посты с типом 15 начиная с февраля и заканчивая сентябрем 2015 лежат в третьем зале, 10-й шкаф, 5-я полка сверху. Конкретный пост сама найдешь, там на полке больше 20-ти штук все равно не помещается.
    - Благодарю!
    Ответ написан
    5 комментариев
  • Как организовать синхронизацию данных БД между разработчиками в период разработки?

    1) соглашусь с Алексей Николаев , если данных немного, и это именно development-данные (т.е. тестовые наборы данных), то миграции подойдут как нельзя лучше;
    2) если же все-таки речь идет о живых данных, то у Оракла есть Oracle Workspace Manager, который отвечает на ваш вопрос "как быть с данными?". Разумеется это компонент Oracle Database, о самостоятельных open-source решениях аналогах не слышал.
    Ответ написан
    Комментировать
  • E-mail вместо id плюсы и минусы?

    1) Так и не понял, вы хотите email вместо логина или вместо id. Начинаете вопрос одним, заканчиваете другим.
    2) Если вместо логина - то что вообще значит "вместо"? Не использовать логин вообще или использовать email для авторизации?
    3) Если вместо id - оно как бы в теории можно, но как бы не стоит. Вы же помните, что вам потом внешние ключи ставить в виде email-ов? И обновлять их при смене адреса пользоватаелем. Правильно, это жесть, поэтому не надо.
    4) А чего вы вообще переживаете про WHERE `email`='почта@домен' - ну авторизовали аутентифицировали человека один раз, в сессию положили его id, дальше выборки по id, в чем задача-то?
    Ответ написан
    1 комментарий