我試圖使用會話處理程序和學說DBAL之間到我的數據庫相同的連接之間的數據庫:共享連接DBAL和會話處理的Symfony2
config.yml
framework:
session:
handler_id: session.handler.one_connection_pdo
services.yml
session.handler.one_connection_pdo:
class: AppBundle\Session\OneConnectionPdoHandler
public: false
arguments:
- "@database_connection"
- []
的appbundle /會話/ OneConnectionPdoHandler.php
namespace AppBundle\Session;
use Doctrine\DBAL\Connection;
use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler;
class OneConnectionPdoHandler extends PdoSessionHandler
{
public function __construct($pdoOrDsn, array $options)
{
if ($pdoOrDsn instanceof Connection) {
$pdoOrDsn = $pdoOrDsn->getWrappedConnection();
}
parent::__construct($pdoOrDsn, $options);
}
}
一切似乎都瀏覽應用程序時的工作,但因爲我得到的錯誤,我不能更新任何實體:
PDOException: There is already an active transaction
at n/a
in .../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 1176
at PDO->beginTransaction()
in .../vendor/doctrine/dbal/lib/Doctrine/DBAL/Connection.php line 1176
at Doctrine\DBAL\Connection->beginTransaction()
in .../vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 373
at Doctrine\ORM\UnitOfWork->commit(null)
in .../vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php line 356
at Doctrine\ORM\EntityManager->flush()
in .../src/AppBundle/Controller/Admin/DistributorsController.php line 66
at AppBundle\Controller\Admin\DistributorsController->editAction(object(Distributor), object(Request))
in line
at call_user_func_array(array(object(DistributorsController), 'editAction'), array(object(Distributor), object(Request)))
in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 139
at Symfony\Component\HttpKernel\HttpKernel->handleRaw(object(Request), '1')
in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/HttpKernel.php line 62
at Symfony\Component\HttpKernel\HttpKernel->handle(object(Request), '1', true)
in .../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/Kernel.php line 169
at Symfony\Component\HttpKernel\Kernel->handle(object(Request))
in .../web/app_dev.php line 31
有分享主義DBAL和自定義PDO處理器之間的連接的方法嗎?
//編輯
我終於發現裏面PdoSessionHandler
類的解決方案。
默認情況下,PDO處理程序在讀取和寫入會話時使用事務。它首先開始交易read()
並承諾close()
。在這之間有一些數據庫操作$em->persist($entity); $em->flush()
,它產生了另一個產生錯誤的事務。
裏面PdoSessionHandler
類,我發現有一個lock_mode
選項,可以設置這樣的:
session.handler.one_connection_pdo:
class: AppBundle\Session\OneConnectionPdoHandler
public: false
arguments:
- "@database_connection"
- { lock_mode: 1 }
當LOCK_MODE設置爲1(PdoSessionHandler::LOCK_ADVISORY
)PDO處理程序將使用諮詢鎖,而不是交易,將有不再有交易錯誤。
典型地,這些種類的當循環訪問一組結果並嘗試在循環中執行數據庫更新時,會發生錯誤。看起來你也有一些實體管理器正在進行,所有的都共享相同的連接對象。其他人可能會有更好的建議,但我會建議僅爲會話代碼創建連接對象:http://symfony.com/doc/current/cookbook/doctrine/multiple_entity_managers.html。這將消除意外的交互。或者可以使用fetchAll而不是查詢循環。 – Cerad
我對這個處理程序進行了一些調查。它看起來是在首次讀取'PdoSessionHandler :: read() - > doRead() - > getSelectSql() - > beginTransaction()'並且直到close()'結束事務時纔開始事務。在教義之間嘗試更改實體:'$ em-> persist($ entity); $ em-> flush()'產生另一個事務並觸發錯誤。我想我現在會堅持使用memcached處理程序。 Thx – piotrekkr
是的。我似乎從Symfony 2的早期版本中記得這一點。無論如何,我從來不希望我的會話信息存儲在生產數據庫中。因此需要會話特定的數據庫和連接。 – Cerad