Вставить / Удалить исполнение - PullRequest
1 голос
/ 01 июня 2009
DB Table: 
id       int(6)
message  char(5)

Я должен добавить запись (сообщение) в таблицу БД. В случае дублирования сообщения (это сообщение уже существует с другим идентификатором), я хочу удалить (или как-то деактивировать) оба сообщения и получить их идентификаторы в ответ.

Можно ли выполнить только один запрос? Любые советы по производительности? ...

P.S. Я использую PostgreSQL.

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

Большое спасибо!

Ответы [ 3 ]

2 голосов
/ 01 июня 2009

Если вы действительно хотите беспокоиться о блокировке, сделайте это.

  1. Таблица ОБНОВЛЕНИЙ SET состояние = «НЕАКТИВНО» ГДЕ id = «ключ»;

    Если это удастся, был дубликат.

    • ВСТАВЬТЕ дополнительную неактивную запись. Делайте со своими дубликатами все, что захотите.

    Если это не помогло, дубликатов не было.

    • ВСТАВИТЬ новую активную запись.
  2. Commit.

Это сразу же захватывает эксклюзивный замок. Альтернативы не так хороши.

  • Начните с ВСТАВКИ, и проверка на наличие дубликатов не захватит блокировку, пока вы не начнете обновление. Непонятно, если это проблема или нет.

  • Для начала с SELECT потребуется добавить LOCK TABLE, чтобы убедиться, что выбор удерживает найденную строку, чтобы ее можно было обновить. Если строка не найдена, вставка будет работать нормально.

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

Учтите это.

  1. Процесс A выполняет LOCK ROW и SELECT, но не находит строки.

  2. Процесс B выполняет LOCK ROW и SELECT, но не находит строки.

  3. Процесс A делает INSERT и COMMIT.

  4. Процесс B делает INSERT и COMMIT. Теперь у вас есть дубликаты активных записей.

Несколько одновременных транзакций вставки / обновления будут работать только с блокировкой на уровне таблицы. Да, это потенциальное замедление. Три правила: (1) Сделайте свои транзакции как можно короче, (2) снимите блокировки как можно быстрее, (3) обработайте взаимные блокировки, повторив попытку.

1 голос
/ 01 июня 2009

Вы можете написать процедуру с обеими этими командами, но может иметь смысл использовать триггер вставки для проверки на наличие дубликатов (или ночного задания, если оно не чувствительно ко времени).

0 голосов
/ 01 июня 2009

Немного сложно понять ваше точное требование. Позвольте мне перефразировать это двумя способами:

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...