Каков предпочтительный способ получить доступ к транзакции для фиксации или отката? - PullRequest
0 голосов
/ 07 марта 2011

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

У меня есть 3 класса обслуживания, которые могут обращаться к одному объекту одноэлементного соединения. Я хочу обернуть эти три вещи в одну транзакцию, поэтому я делаю это:

try {
  $service1 = new ServiceOne;
  $service2 = new ServiceTwo;
  $service3 = new ServiceThree;

  $service1->insertRec1($data);
  $service2->deleteRec2($data);
  $service3->updateRec3($data);

  $service1->getSingletonConnection()->commit();
}
catch(Exception $ex) {
  $service1->getSingletonConnection()->rollback();
}

Объект соединения, возвращаемый getSingletonConnection, является просто оболочкой для соединения oci8, а фиксация - oci_commit; Откат составляет oci_rollback.

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

Есть ли лучший способ обработки транзакций?

Ответы [ 2 ]

2 голосов
/ 08 марта 2011

это неправильно, чтобы получить доступ к соединение через любой произвольный объект обслуживания.

Я согласен с вами на 100%.

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

Таким образом, ваш текущий код будет изменен на что-то вроде:

try {
  $conn = getSingletonConnection();
  $service1 = new ServiceOne($conn);
  $service2 = new ServiceTwo($conn);
  $service3 = new ServiceThree($conn);

  $service1->insertRec1($data);
  $service2->deleteRec2($data);
  $service3->updateRec3($data);

  $conn->commit();
}
catch(Exception $ex) {
  $conn->rollback();
}

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

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

1 голос
/ 07 марта 2011

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

  • Поддерживать текущий единственный объект соединения для каждой из трех служб
  • Поддерживать отдельные соединения (с соответствующими издержками) для каждой службы и фиксировать / откатывать каждуюотдельное соединение отдельно (не особо безопасно, потому что вы не можете гарантировать согласованность ACID)

Как способ обойти два отдельных экземпляра базы данных, к которым вы подключаетесь: используйте ссылки db, чтобы выподключаться только к одной базе данных

...