2011-11-04 4 views
0

У меня есть сценарий, в котором, как мне кажется, мне нужно заблокировать таблицу против всех действий (чтение и запись). Я использую Propel 1.6.x и намерен написать небольшую дополнительную библиотеку для обработки блокировки.Библиотека блокировки базы данных с базой данных для PHP

My use case - это таблица версий, в которой есть первичный ключ (id, создатель, версия). Пара столбцов (id, creator) на самом деле является PK в другой таблице. Когда новая строка вставлена, MAX (версия) считывается в PHP-коде, а затем вставляется в класс row для последующего сохранения. Между максимумом и сохранением существует потенциал состояния гонки, когда другой процесс может получить одно и то же максимальное значение, и тогда, конечно, одна из вставок потерпит неудачу из-за неединственности.

Чтобы избежать необходимости замков, я бы предпочел использовать подзапрос для спасения, что-то вроде:

INSERT INTO 
    test_model_test_organiser_versionable 
(id, creator, version) 
VALUES (
    3, 
    1, 
    (
     SELECT COALESCE(MAX(version), 1) 
     FROM test_model_test_organiser_versionable 
     WHERE id = 3 
     AND creator = 1 
    ) 
); 

Однако это не поддерживается в Propel, и если я делаю это через PDO I не будет (афайк) иметь способ узнать значение, данное части «версии» составного ПК.

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

Итак ... я чувствую, что обертывание max & Сохранение вызовов в блокировке - это путь. Это должно было бы заблокировать всю таблицу IMO и защититься от чтения, а также от записи (иначе последующий макс-вызов не будет ждать и, следовательно, приведет к отказу от неединственности снова).

Мне нужно это, чтобы работать со всеми платформами, поддерживаемыми Propel, поэтому - если нет лучшего подхода, который я должен принять - есть ли библиотека PHP, которая будет делать эту блокировку в отношении любой базы данных PDO? Если нет, я могу сделать это сам - но приятно, если кто-то еще провел тестирование осла-работы против множества dbs (настроил MSSQL Server? - нет спасибо :)

+0

Приложение: Я обнаружил, что в PostgreSQL можно выполнить 'INSERT INTO x ... RETURNING my_column' - это исправить, но, к сожалению, не нейтрально! – halfer

+0

Я написал класс для PostgreSQL, который блокирует таблицу, используя «LOCK test_model_test_organiser_versionable IN SHARE ROW EXCLUSIVE MODE» - и это, похоже, решает проблему (мне нужно будет найти эквиваленты для всех других платформ db). Однако ответы все же приветствуются. – halfer

ответ

1

Я пошел с полной блокировкой стола в то время как MAX() и INSERT/UPDATE выполнены. Я нашел эти работали:

  • MySQL: LOCK TABLES my_table WRITE
  • PostgreSQL: LOCK TABLE my_table IN SHARE ROW EXCLUSIVE MODE

Я планирую посмотреть и проверить то же самое для Oracle, MSSQL и SQLite в свое время - но первые два вероятно, самый популярный для проектов F/OSS.

+0

О да, если кто-то может предоставить эквивалент для любой из моих недостающих платформ, они могут иметь галочку! – halfer