Pdo, postgresql, lastinsertid

Европа - быстрые серверы на дисках NVMe от $5 / Русский датацентр от 199руб

Тема в разделе "PHP & Postgres", создана пользователем junior17, 10 мар 2018.

Метки:
  1. junior17

    junior17 Новичок

    Сообщения:
    26
    Ваш город:
    Москва, город Москва, Россия
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Здравствуйте,

    В документации pdo написано:

    Но у меня в postgre 9.6 $pdo->lastInsertId() без указания имени последовательности возвращает последнюю запись SEQUENCE.

    Пример:

    Код:
    CREATE SEQUENCE users_id_seq
        START WITH 1
        INCREMENT BY 1
        NO MINVALUE
        NO MAXVALUE
        CACHE 1;
    
    CREATE TABLE users (
        id bigint DEFAULT nextval('users_id_seq'::regclass) NOT NULL,
        name character varying NOT NULL,
        PRIMARY KEY(id)
    );
    
    $pdo = $dbh->prepare("INSERT INTO users (name) VALUES(?)");
    $pdo->bindValue(1, $name);
    $pdo->execute();
    $pdo->lastInsertId(); /* Возвращает последнего пользователя */
    У меня в коде много где используется $pdo->lastInsertId(), поэтому немного настораживает, возможно ли то, что эта функция вернет не то, что требуется? Просьба разъяснить этот момент. Спасибо.
     
    Последнее редактирование: 10 мар 2018
  2. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.958
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    junior17 и Adelf нравится это.
  3. Adelf

    Adelf Laravel&PhpStorm Команда форума

    Сообщения:
    3.321
    Ваш город:
    Казань
    Address:
    Kazan, Russia
    Country:
    Location on Map:
    приучись сначала узнавать id а лишь потом создавать сущность. это даст некоторый профит в будущем.
     
  4. junior17

    junior17 Новичок

    Сообщения:
    26
    Ваш город:
    Москва, город Москва, Россия
    Address:
    Moscow, Russia
    Country:
    Location on Map:
  5. junior17

    junior17 Новичок

    Сообщения:
    26
    Ваш город:
    Москва, город Москва, Россия
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Можно поподробнее?
     
  6. AnrDaemon

    AnrDaemon Продвинутый новичок

    Сообщения:
    4.609
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Куда уж подробнее? Самый простой способ: создавай пустую сущность в БД, узнавай её Id, потом уже используй этот Id при сохранении настоящей сущности.
     
  7. Adelf

    Adelf Laravel&PhpStorm Команда форума

    Сообщения:
    3.321
    Ваш город:
    Казань
    Address:
    Kazan, Russia
    Country:
    Location on Map:
    @AnrDaemon, а не проще просто узнавать следующее значение секвенса и создавать сущность с этим id?
     
  8. AnrDaemon

    AnrDaemon Продвинутый новичок

    Сообщения:
    4.609
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Если это доступно - да. Так проще. При условии, что это узнанное значение гарантированно не будет кем-то использовано, пока я создаю сущность.
     
  9. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    7.081
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    если я правильно тебя понимаю, ты советуешь делать сначала INSERT, потом ->lastInsertedId(), затем UPDATE
    расскажи, пожалуйста, какой профит это приносит в рамках одного процесса
    цена очевидна: UPDATE - относительно дорогая операция, и без специального проектирования приводит к дедлокам или race condition намного чаще, чем INSERT
     
  10. AnrDaemon

    AnrDaemon Продвинутый новичок

    Сообщения:
    4.609
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Единственное "специальное проектирование", которое необходимо - явно избегать работы с пустыми сущностями в открытой части проекта. Только в админке/API, только с целью их перезаписи/удаления.
    И как UPDATE может привести к дедлоку или гонке? Сущность уже создана, но она пустая и проект её не воспринимает и не ссылается на неё нигде.
     
  11. Adelf

    Adelf Laravel&PhpStorm Команда форума

    Сообщения:
    3.321
    Ваш город:
    Казань
    Address:
    Kazan, Russia
    Country:
    Location on Map:
    это @AnrDaemon советует.
    Я советую узнать значение секвенса.

    это ж секвенсы. Они автоматом инкрементятся. Там все атомарно.
     
  12. AnrDaemon

    AnrDaemon Продвинутый новичок

    Сообщения:
    4.609
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Я рад, что "это ж сиквенсы", вот только писал я это не для тех, кому это "ну это ж", а в общем случае.
     
  13. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.958
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    "В общем случае" сиквенсы прекрасно эмулируются через table sequences ( sequenceType, value ).

    Ну или UUID вообще.
     
  14. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    7.081
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    Первое.
    Эмуляция через отдельную таблицу?
    Узнать sequence, и использовать отдельно от записи?
    В общем случае?

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

    Вот UUID - лучшее решение в общем случае, да
     
    Последнее редактирование: 11 мар 2018
    WMix нравится это.
  15. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    7.081
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    Второе.
    Update приводит к race condition, если другая транзакция работает со списком сущностей. Если эта другая транзакция выполняет SELECT FOR UPDATE по диапазону (а как еще?) - несколько параллельных update-ов могут привести к дедлоку.

    Третье.
    Таким образом, у нас появляется еще одно архитектурное ограничение, неявное соглашение, которое неприемлемо в сервисной архитектуре.
    Преимуществ нет никаких, зато ограничений - целая пачка.
    Герой костыля и монолита.
     
    Фанат нравится это.
  16. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.958
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Под "общим случаем" я тут имел ввиду:
    a) СУБД без поддержки сиквенсов,
    б) ситуации, когда надо поддерживать общий сиквенс при шардинге по нескольким серверам (тут может быть даже и не таблица, а какой-нибудь счетчик в Redis).

    Сам я предпочитаю UUID, но почему-то у многих к нему какая-то личная неприязнь, что ли.

    Про dummy insert и последующий update обсуждать не хочу, я это тоже считаю ерундой :)
     
  17. grigori

    grigori ( ͡° ͜ʖ ͡°) Команда форума

    Сообщения:
    7.081
    Ваш город:
    Stormwind
    Address:
    Scottsdale, United States
    Country:
    Location on Map:
    @fixxxer, в разделе про постгрес "общий случай" с СУБД без поддержки сиквенсов, шардинга и полей UUID смотрится забавно. Не будем показывать пальцем )))
     
  18. AnrDaemon

    AnrDaemon Продвинутый новичок

    Сообщения:
    4.609
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Ну, да, да…
    *ушёл*
     
  19. fixxxer

    fixxxer К.О. Партнер клуба

    Сообщения:
    12.958
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    ну не я ж начал про мыскль. :)
     
  20. Фанат

    Фанат oncle terrible Команда форума

    Сообщения:
    39.946
    Ваш город:
    Moscow, Russia
    Address:
    Moscow, Russia
    Country:
    Location on Map:
    Ок, с идеей зачем-то инсерт+апдейт вместо просто инсерта разобрались. Кстати, про бенефиты мы так и не услышали

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