Second Level Cache

Der Second Level Cache wurde entwickelt, um den Umfang der erforderlichen Datenbankzugriffe zu reduzieren. Es befindet sich zwischen Ihrer Anwendung und der Datenbank, um die Anzahl der Datenbankzugriffe so weit wie möglich zu vermeiden.

Quelle: https://www.doctrine-project.org/[...]

Konfiguriation

Der Cache ist brandbox integriert und standardmäßig aktiv. Es ist möglich diesen Cache zu deaktivieren und über die config.php zu konfigurieren. Das folgende Beispiel, zeigt zusätzlich die Default-Werte:

'cache' => [ '2nd-lc' => [ 'active' => true, 'logger' => false, 'lifetime' => 24 * 60 * 60 // = 24h ] ]

Definition im Entity

Das Entity erhält weitere Informationen über den Umgang des Caches mit diesem Entity.

use Doctrine\ORM\Mapping\Cache; /** * @Entity * @Cache(usage="NONSTRICT_READ_WRITE", region="brandbox/app-xyz") * ... **/ class Entity ... { }

Umgang mit unterschiedlichen Datensatz-Arten

Je nach Zweck sollte ein Entity in den Cache oder nicht. Es gibt folgende Möglichkeiten:

Nicht in den Cache

Datensätze die nur einmal geschrieben werden und extrem selten abgerufen werden, gehören nicht in den Cache. Zur Verwendung wird die Cache-Class nicht, wie im obigen Beispiel, in das Entity aufgenommen.
Beispiel: Logs 

usage="READ_ONLY"

Datensätze die nur ein Mal geschrieben und später nur gelesen oder gelöscht (also nicht aktualisiert) werden.
Beispiel: Automatisch generierte Tokens

usage="NONSTRICT_READ_WRITE"

Datensätze mit denen alle Operationen möglich sein müssen: Anlegen, Lesen, Aktualisieren, Löschen. 
Beispiel: Artikel, Preise, uvm.

Das ist der häufigste und übliche Fall.

Connection

In der Connection wird der Cache aktiviert: \Brandbox\Framework\Brandbox\Doctrine\Lib\Connection\Connection::enableSecondLevelCache

Cacheable oder nicht

Ein Query ist Cacheable wenn ein Entity im Result ausgeliefert wird. Ist das nicht der Fall, kommt es zum Fehler (WSOD). Man erkennt das an der Hydration.
Letztlich ist „nur“ dieses Objekt cacheable: \Doctrine\ORM\AbstractQuery::HYDRATE_OBJECT

Evict

Wird ein Datensatz verändert (DELETE, INSERT, UPDATE) muss der verändernde Query ein Hint erhalten:

Beispiel
$qb ->delete($class, $identifier) ->where($expr->eq($identifier . '.id', ':id')) ->setParameter(':id', $id) ->getQuery() ->setHint(ORM\Query::HINT_CACHE_EVICT, true) ->execute() ;