1
0
mirror of synced 2024-12-05 03:06:05 +03:00
This commit is contained in:
fabios 2013-10-17 12:11:56 -04:00
parent d135e402bb
commit fb98277783
17 changed files with 80 additions and 64 deletions

View File

@ -2,7 +2,7 @@ The Second Level Cache
====================== ======================
The Second Level Cache is designed to reduce the amount of necessary database access. The Second Level Cache is designed to reduce the amount of necessary database access.
It sits between your application and the database to avoid the number of database hits as many as possible. It sits between your application and the database to avoid the number of database hits as much as possible.
When turned on, entities will be first searched in cache and if they are not found, When turned on, entities will be first searched in cache and if they are not found,
a database query will be fired an then the entity result will be stored in a cache provider. a database query will be fired an then the entity result will be stored in a cache provider.
@ -22,6 +22,9 @@ Each entity class, collection association and query has its region, where values
Caching Regions are specific region into the cache provider that might store entities, collection or queries. Caching Regions are specific region into the cache provider that might store entities, collection or queries.
Each cache region resides in a specific cache namespace and has its own lifetime configuration. Each cache region resides in a specific cache namespace and has its own lifetime configuration.
Notice that when caching collection and queries only identifiers are stored.
The entity values will be stored in its own region
Something like below for an entity region : Something like below for an entity region :
.. code-block:: php .. code-block:: php
@ -60,8 +63,7 @@ A query region might be something like :
.. note:: .. note::
Notice that when caching collection and queries only identifiers are stored. The following data structures represents now the cache will looks like, this is not actual cached data.
The entity values will be stored in its own region
.. _reference-second-level-cache-regions: .. _reference-second-level-cache-regions:
@ -80,6 +82,11 @@ It allows you to provide your own cache implementation that might take advantage
If you want to support locking for ``READ_WRITE`` strategies you should implement ``ConcurrentRegion``; ``CacheRegion`` otherwise. If you want to support locking for ``READ_WRITE`` strategies you should implement ``ConcurrentRegion``; ``CacheRegion`` otherwise.
Cache region
~~~~~~~~~~~~
Defines a contract for accessing a particular region.
``Doctrine\ORM\Cache\Region`` ``Doctrine\ORM\Cache\Region``
Defines a contract for accessing a particular cache region. Defines a contract for accessing a particular cache region.
@ -111,7 +118,7 @@ Defines a contract for accessing a particular cache region.
* *
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved. * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved.
* *
* @return \Doctrine\ORM\Cache\CacheEntry The cached entry or NULL * @return \Doctrine\ORM\Cache\CacheEntry|null The cached entry or NULL
*/ */
public function get(CacheKey $key); public function get(CacheKey $key);
@ -138,6 +145,14 @@ Defines a contract for accessing a particular cache region.
} }
Concurrent cache region
~~~~~~~~~~~~~~~~~~~~~~~
A ``Doctrine\ORM\Cache\ConcurrentRegion`` is designed to store concurrently managed data region.
By default, Doctrine provides a very simple implementation based on file locks ``Doctrine\ORM\Cache\Region\FileLockRegion``.
If you want to use an ``READ_WRITE`` cache, you should consider providing your own cache region.
``Doctrine\ORM\Cache\ConcurrentRegion`` ``Doctrine\ORM\Cache\ConcurrentRegion``
Defines contract for concurrently managed data region. Defines contract for concurrently managed data region.
@ -166,6 +181,9 @@ Defines contract for concurrently managed data region.
public function unlock(CacheKey $key, Lock $lock); public function unlock(CacheKey $key, Lock $lock);
} }
Cache region
~~~~~~~~~~~~
``Doctrine\ORM\Cache\TimestampRegion`` ``Doctrine\ORM\Cache\TimestampRegion``
Tracks the timestamps of the most recent updates to particular entity. Tracks the timestamps of the most recent updates to particular entity.
@ -179,7 +197,7 @@ Tracks the timestamps of the most recent updates to particular entity.
/** /**
* Update an specific key into the cache region. * Update an specific key into the cache region.
* *
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to lock. * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to update the timestamp.
* *
* @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region.
*/ */
@ -364,8 +382,8 @@ To specify a default lifetime for all regions or specify a different lifetime fo
$regionConfig = $cacheConfig->getRegionsConfiguration(); $regionConfig = $cacheConfig->getRegionsConfiguration();
//Cache Region lifetime //Cache Region lifetime
$regionConfig->setLifetime('my_entity_region', 3600); $regionConfig->setLifetime('my_entity_region', 3600); // Time to live for a specific region; In seconds
$regionConfig->setDefaultLifetime(7200); $regionConfig->setDefaultLifetime(7200); // Default time to live; In seconds
Cache Log Cache Log
@ -672,7 +690,7 @@ Basic entity cache
$em->clear(); // Clear entity manager $em->clear(); // Clear entity manager
$country = $em->find('Country', 1); // Retrieve item from cache $country1 = $em->find('Country', 1); // Retrieve item from cache
$country->setName("New Name"); $country->setName("New Name");
$em->persist($state); $em->persist($state);
@ -680,7 +698,8 @@ Basic entity cache
$em->clear(); // Clear entity manager $em->clear(); // Clear entity manager
$country = $em->find('Country', 1); // Retrieve item from cache $country2 = $em->find('Country', 1); // Retrieve item from cache
// Notice that $country1 and $country2 are not the same instance.
Association cache Association cache
@ -759,6 +778,8 @@ The query cache stores the results of the query but as identifiers, entity value
->setCacheable(true) ->setCacheable(true)
->getResult(); ->getResult();
$em->clear()
// Check if query result is valid and load entities from cache // Check if query result is valid and load entities from cache
$result2 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name') $result2 = $em->createQuery('SELECT c FROM Country c ORDER BY c.name')
->setCacheable(true) ->setCacheable(true)
@ -806,15 +827,16 @@ Using the last update timestamps as part of the query key invalidate the cache k
$entities = $em->getRepository('Entity\Country')->findAll(); $entities = $em->getRepository('Entity\Country')->findAll();
// load from query and entities from cache.. // load from query and entities from cache..
$entities = $em->getRepository('Country')->findAll(); $entities = $em->getRepository('Entity\Country')->findAll();
// update the timestamp cache region for Country // update the timestamp cache region for Country
$em->persist(new Country('zombieland')); $em->persist(new Country('zombieland'));
$em->flush(); $em->flush();
$em->clear(); $em->clear();
// Reload the query from database. // Reload from database.
$entities = $em->getRepository('Country')->findAll(); // At this point the query cache key if not logger valid, the select goes straight
$entities = $em->getRepository('Entity\Country')->findAll();
Cache API Cache API
--------- ---------
@ -843,8 +865,9 @@ Limitations
Composite primary key Composite primary key
~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~
Composite primary key are supported by second level cache, however when one of the keys is an association Composite primary key are supported by second level cache,
the cached entity should always be retrieved using the association identifier. however when one of the keys is an association the cached entity should always be retrieved using the association identifier.
For performance reasons the cache API does not extract from composite primary key.
.. code-block:: php .. code-block:: php
@ -871,29 +894,19 @@ the cached entity should always be retrieved using the association identifier.
// Supported // Supported
/** @var $article Article */ /** @var $article Article */
$article = $this->_em->find("Article", 1); $article = $em->find('Article', 1);
// Supported // Supported
/** @var $article Article */ /** @var $article Article */
$article = $this->_em->find("Article", $article); $article = $em->find('Article', $article);
// Supported // Supported
$id = array('source' => 1, 'target' => 2); $id = array('source' => 1, 'target' => 2);
$reference = $this->_em->find("Reference", $id); $reference = $em->find('Reference', $id);
// NOT Supported // NOT Supported
$id = array('source' => new Article(1), 'target' => new Article(2)); $id = array('source' => new Article(1), 'target' => new Article(2));
$reference = $this->_em->find("Reference", $id); $reference = $em->find('Reference', $id);
Concurrent cache region
~~~~~~~~~~~~~~~~~~~~~~~
A ``Doctrine\\ORM\\Cache\\ConcurrentRegion`` is designed to store concurrently managed data region.
By default, Doctrine provides a very simple implementation based on file locks ``Doctrine\\ORM\\Cache\\Region\\FileLockRegion``.
If you want to use an ``READ_WRITE`` cache, you should consider providing your own cache region.
for more details about how to implement a cache region please see :ref:`reference-second-level-cache-regions`
DELETE / UPDATE queries DELETE / UPDATE queries

View File

@ -137,19 +137,19 @@ abstract class AbstractQuery
/** /**
* Second level cache region name. * Second level cache region name.
* *
* @var string * @var string|null
*/ */
protected $cacheRegion; protected $cacheRegion;
/** /**
* Second level query cache mode. * Second level query cache mode.
* *
* @var integer * @var integer|null
*/ */
protected $cacheMode; protected $cacheMode;
/** /**
* @var \Doctrine\ORM\Cache\Logging\CacheLogger * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null
*/ */
protected $cacheLogger; protected $cacheLogger;
@ -206,7 +206,7 @@ abstract class AbstractQuery
*/ */
public function setCacheRegion($cacheRegion) public function setCacheRegion($cacheRegion)
{ {
$this->cacheRegion = $cacheRegion; $this->cacheRegion = (string) $cacheRegion;
return $this; return $this;
} }
@ -245,7 +245,7 @@ abstract class AbstractQuery
*/ */
public function setLifetime($lifetime) public function setLifetime($lifetime)
{ {
$this->lifetime = $lifetime; $this->lifetime = (integer) $lifetime;
return $this; return $this;
} }
@ -264,7 +264,7 @@ abstract class AbstractQuery
*/ */
public function setCacheMode($cacheMode) public function setCacheMode($cacheMode)
{ {
$this->cacheMode = $cacheMode; $this->cacheMode = (integer) $cacheMode;
return $this; return $this;
} }

View File

@ -165,7 +165,7 @@ interface Cache
/** /**
* Evicts all cached query results under the given name, or default query cache if the region name is NULL. * Evicts all cached query results under the given name, or default query cache if the region name is NULL.
* *
* @param string $regionName The cache name associated to the queries being cached. * @param string|null $regionName The cache name associated to the queries being cached.
*/ */
public function evictQueryRegion($regionName = null); public function evictQueryRegion($regionName = null);
@ -179,9 +179,9 @@ interface Cache
/** /**
* Get query cache by region name or create a new one if none exist. * Get query cache by region name or create a new one if none exist.
* *
* @param regionName Query cache region name, or default query cache if the region name is NULL. * @param string|null $regionName Query cache region name, or default query cache if the region name is NULL.
* *
* @return \Doctrine\ORM\Cache\QueryCache The Query Cache associated with the region name. * @return \Doctrine\ORM\Cache\QueryCache The Query Cache associated with the region name.
*/ */
public function getQueryCache($regionName = null); public function getQueryCache($regionName = null);
} }

View File

@ -35,22 +35,22 @@ use Doctrine\ORM\Cache\TimestampQueryCacheValidator;
class CacheConfiguration class CacheConfiguration
{ {
/** /**
* @var \Doctrine\ORM\Cache\CacheFactory * @var \Doctrine\ORM\Cache\CacheFactory|null
*/ */
private $cacheFactory; private $cacheFactory;
/** /**
* @var \Doctrine\ORM\Cache\RegionsConfiguration * @var \Doctrine\ORM\Cache\RegionsConfiguration|null
*/ */
private $regionsConfig; private $regionsConfig;
/** /**
* @var \Doctrine\ORM\Cache\Logging\CacheLogger * @var \Doctrine\ORM\Cache\Logging\CacheLogger|null
*/ */
private $cacheLogger; private $cacheLogger;
/** /**
* @var \Doctrine\ORM\Cache\QueryCacheValidator * @var \Doctrine\ORM\Cache\QueryCacheValidator|null
*/ */
private $queryValidator; private $queryValidator;

View File

@ -51,7 +51,7 @@ class DefaultCache implements Cache
private $cacheFactory; private $cacheFactory;
/** /**
* @var array<\Doctrine\ORM\Cache\QueryCache> * @var \Doctrine\ORM\Cache\QueryCache[]
*/ */
private $queryCaches = array(); private $queryCaches = array();

View File

@ -57,17 +57,17 @@ class DefaultCacheFactory implements CacheFactory
private $regionsConfig; private $regionsConfig;
/** /**
* @var \Doctrine\ORM\Cache\TimestampRegion * @var \Doctrine\ORM\Cache\TimestampRegion|null
*/ */
private $timestampRegion; private $timestampRegion;
/** /**
* @var array * @var \Doctrine\ORM\Cache\Region[]
*/ */
private $regions; private $regions = array();
/** /**
* @var string * @var string|null
*/ */
private $fileLockRegionDirectory; private $fileLockRegionDirectory;
@ -86,7 +86,7 @@ class DefaultCacheFactory implements CacheFactory
*/ */
public function setFileLockRegionDirectory($fileLockRegionDirectory) public function setFileLockRegionDirectory($fileLockRegionDirectory)
{ {
$this->fileLockRegionDirectory = $fileLockRegionDirectory; $this->fileLockRegionDirectory = (string) $fileLockRegionDirectory;
} }
/** /**
@ -200,7 +200,7 @@ class DefaultCacheFactory implements CacheFactory
if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) { if ($cache['usage'] === ClassMetadata::CACHE_USAGE_READ_WRITE) {
if ( ! $this->fileLockRegionDirectory) { if ( ! $this->fileLockRegionDirectory) {
throw new \RuntimeException( throw new \LogicException(
'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' . 'If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, ' .
'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you what to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). ' 'The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you what to use it please provide a valid directory, DefaultCacheFactory#setFileLockRegionDirectory(). '
); );

View File

@ -51,7 +51,7 @@ interface Region
* *
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved. * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to be retrieved.
* *
* @return \Doctrine\ORM\Cache\CacheEntry The cached entry or NULL * @return \Doctrine\ORM\Cache\CacheEntry|null The cached entry or NULL
* *
* @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the item or region. * @throws \Doctrine\ORM\Cache\CacheException Indicates a problem accessing the item or region.
*/ */

View File

@ -31,12 +31,12 @@ class RegionsConfiguration
/** /**
* @var array * @var array
*/ */
private $lifetimes; private $lifetimes = array();
/** /**
* @var array * @var array
*/ */
private $lockLifetimes; private $lockLifetimes = array();
/** /**
* @var integer * @var integer
@ -54,8 +54,8 @@ class RegionsConfiguration
*/ */
public function __construct($defaultLifetime = 3600, $defaultLockLifetime = 60) public function __construct($defaultLifetime = 3600, $defaultLockLifetime = 60)
{ {
$this->defaultLifetime = $defaultLifetime; $this->defaultLifetime = (integer) $defaultLifetime;
$this->defaultLockLifetime = $defaultLockLifetime; $this->defaultLockLifetime = (integer) $defaultLockLifetime;
} }
/** /**
@ -71,7 +71,7 @@ class RegionsConfiguration
*/ */
public function setDefaultLifetime($defaultLifetime) public function setDefaultLifetime($defaultLifetime)
{ {
$this->defaultLifetime = $defaultLifetime; $this->defaultLifetime = (integer) $defaultLifetime;
} }
/** /**
@ -87,7 +87,7 @@ class RegionsConfiguration
*/ */
public function setDefaultLockLifetime($defaultLockLifetime) public function setDefaultLockLifetime($defaultLockLifetime)
{ {
$this->defaultLockLifetime = $defaultLockLifetime; $this->defaultLockLifetime = (integer) $defaultLockLifetime;
} }
/** /**

View File

@ -31,7 +31,7 @@ interface TimestampRegion extends Region
/** /**
* Update an specific key into the cache region. * Update an specific key into the cache region.
* *
* @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to lock. * @param \Doctrine\ORM\Cache\CacheKey $key The key of the item to update the timestamp.
* *
* @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region. * @throws \Doctrine\ORM\Cache\LockException Indicates a problem accessing the region.
*/ */

View File

@ -41,4 +41,4 @@ final class Cache implements Annotation
* @var string Cache region name. * @var string Cache region name.
*/ */
public $region; public $region;
} }

View File

@ -594,7 +594,7 @@ class ClassMetadataInfo implements ClassMetadata
/** /**
* @var array * @var array
*/ */
public $cache; public $cache = null;
/** /**
* The ReflectionClass instance of the mapped class. * The ReflectionClass instance of the mapped class.
@ -875,7 +875,7 @@ class ClassMetadataInfo implements ClassMetadata
} }
if ($this->cache) { if ($this->cache) {
$serialized[] = "cache"; $serialized[] = 'cache';
} }
return $serialized; return $serialized;

View File

@ -727,6 +727,8 @@ class XmlDriver extends FileDriver
} }
/** /**
* Parse / Normalize the cache configuration
*
* @param SimpleXMLElement $cacheMapping * @param SimpleXMLElement $cacheMapping
* *
* @return array * @return array

View File

@ -732,6 +732,8 @@ class YamlDriver extends FileDriver
} }
/** /**
* Parse / Normalize the cache configuration
*
* @param array $cacheMapping * @param array $cacheMapping
* *
* @return array * @return array

View File

@ -32,4 +32,4 @@ class CacheMetadataListener
$metadata->enableAssociationCache($mapping['fieldName'], $cache); $metadata->enableAssociationCache($mapping['fieldName'], $cache);
} }
} }
} }

View File

@ -7,4 +7,4 @@ use Doctrine\ORM\Cache\CacheEntry;
class CacheEntryMock extends \ArrayObject implements CacheEntry class CacheEntryMock extends \ArrayObject implements CacheEntry
{ {
} }

View File

@ -6,9 +6,8 @@ use Doctrine\ORM\Cache\CacheKey;
class CacheKeyMock extends CacheKey class CacheKeyMock extends CacheKey
{ {
function __construct($hash) function __construct($hash)
{ {
$this->hash = $hash; $this->hash = $hash;
} }
} }

View File

@ -252,7 +252,7 @@ class DefaultCacheFactoryTest extends OrmTestCase
} }
/** /**
* @expectedException RuntimeException * @expectedException LogicException
* @expectedExceptionMessage If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you what to use it please provide a valid directory * @expectedExceptionMessage If you want to use a "READ_WRITE" cache an implementation of "Doctrine\ORM\Cache\ConcurrentRegion" is required, The default implementation provided by doctrine is "Doctrine\ORM\Cache\Region\FileLockRegion" if you what to use it please provide a valid directory
*/ */
public function testInvalidFileLockRegionDirectoryException() public function testInvalidFileLockRegionDirectoryException()