Bug Report #1220
Database caching breaks when using two databases with the same prefix
| Status: | Closed | Start date: | ||
|---|---|---|---|---|
| Priority: | High | Due date: | ||
| Assignee: | % Done: | 100% |
||
| Category: | Libraries:Database | |||
| Target version: | 2.3.3 | |||
| Resolution: | fixed | Points: |
Description
In the below test case, queries are being cached across databases and invalid results are returned. The sleep calls are to identify when caching is and is not taking place.
// Server and credentials
$connection = array(
'type' => 'mysql',
'host' => 'localhost',
'socket' => TRUE,
'user' => 'root',
'pass' => 'password',
);
$db1 = Database::instance('first', array(
'cache' => TRUE,
'connection' => array_merge($connection, array('database' => 'testfirst')),
));
$db2 = Database::instance('second', array(
'cache' => TRUE,
'connection' => array_merge($connection, array('database' => 'testsecond')),
));
$db1->query('CREATE TABLE testtable ( firstfield integer )');
$db1->query('INSERT INTO testtable VALUES ( 1 )');
$db1->query('INSERT INTO testtable VALUES ( 2 )');
// CREATE statement is cached
$db1->clear_cache();
$db2->query('CREATE TABLE testtable ( firstfield integer )');
$db2->query('INSERT INTO testtable VALUES ( 5 )');
// Clear all caches
$db1->clear_cache();
$db2->clear_cache();
// These queries should return different results
$result1 = $db1->query('SELECT *, SLEEP(0.5) FROM testtable')->as_array(); // 1
$result2 = $db2->query('SELECT *, SLEEP(0.5) FROM testtable')->as_array(); // 2
$db2->clear_cache();
// Correct results are obtained after clearing the cache
$result3 = $db2->query('SELECT *, SLEEP(0.5) FROM testtable')->as_array(); // 3
// These queries should still be cached
$db1->query('SELECT *, SLEEP(0.5) FROM testtable')->as_array(); // 4
$db2->query('SELECT *, SLEEP(0.5) FROM testtable')->as_array(); // 5
$db1->query('DROP TABLE testtable');
// DROP statement is cached
$db1->clear_cache();
$db2->query('DROP TABLE testtable');
Current Results:
- Queries 1 and 3 are not cached.
- Queries 2, 4, and 5 are cached.
- Results 1 and 2 match.
- Results 2 and 3 differ.
- Queries 1, 2, and 3 should not be cached.
- Queries 4 and 5 should be cached.
- Results 1 and 2 should differ.
- Results 2 and 3 should match.
Solution:
Query caching should happen per DB config group.
Related issues
Associated revisions
fixing #1220 - thanks chris
History
Updated by Bob - almost 3 years ago
I think a more elegant solution would be to push the config group name to the drivers and then append the name to the SQL statement before hashing the query.
Updated by Chris Bandy almost 3 years ago
Using a key to partition a class member for each inherited instance is not correct, IMO.
Each instance of Database_Driver manages a single connection to a database, and queries should be cached per connection (i.e., not cached across connections.)
$db1 = new Database_Driver($config1); $db2 = new Database_Driver($config2);
These two objects should not share a query cache.
Updated by John Heathco over 2 years ago
- Resolution set to fixed
Updated by John Heathco over 2 years ago
- Status changed from New to Closed
- % Done changed from 0 to 100
Applied in changeset r4343.