Dead end with apc_exists & apc_add? (apc & php)

I wonder if anyone found weird behavior with apc_exists() , a behavior that causes the whole WAMP server to freeze when used together with apc_add() or apc_store() ? After a long “debugging” session and minimizing the problem, I ended up with the following code that caused WAMP to crash.

As far as I can tell, accessing the various keys requires 1 apc_exists() and 2 apc_add() . [so this sounds like a dead end problem] I run this script in chrome and then break the F5 key until I get a rand-thingy reversal. At this time or for the first time, it usually hangs.

 <?php $result = "asdfioasdjfoasdjf"; if(apc_exists("asdf")) { echo("#1<br/>"); apc_add("launcher", $result, 1); } else { echo("#2<br/>"); $result = "asdfasdfasdf"; apc_add("launcher", $result, 10); } if(rand(0,100) < 4) { echo("#stored data!<br/>"); apc_add("asdf", "2130130", 1); } ?> 

My system / setup:
Windows 7 64bit
WAMP 2.2d 32bit
PHP version 5.3.10
apc version 3.1.9 | $ Version: 325040 $

Am I doing something wrong in the code? Is this related to / wamp windows or does it exist in other environments and php / apc versions? In the above case, if I replace apc_exists() with apc_fetch() , the system does not crash, does anyone know why?

+7
source share
2 answers

I believe I have found a reason. It all boils down to being well said here on SO:

First, it’s important to know that if you try to save a key that already exists with a specific TTL and ttl has not yet passed, a new record will be created; it doesn’t matter if the key is the same, there will be two records of the same key inside it.

Secondly, APC may fail (skip). Even when there is no obvious reason for this. What for? APC seems to have been created in favor of speed over consistency, which means that when the APC driver is busy doing some cleanup, it just returns NULL, rather than waiting until it is executed, even though the data exists . This long version is here: http://phpadvent.org/2010/share-and-enjoy-by-gopal-vijayaraghavan

So what happens in the specific case mentioned in the question? The time between each request is shorter than 1 second, indicated by the TTL of the keys, so duplicates can occur if you try to save the key here. "But, using apc_add, should you not guarantee that the key is stored only if it does not already exist?" Apparently, this is not so: this is what causes the deadlock to be random: sometimes apc_add will work as you expected, some others will miss, that is, apc_add does not understand that there is another existing key, even if it exists. This is probably not a problem if TTL = 0, because in this case the key is simply overwritten, but in the specific case of the question it will keep a duplicate as a result of an erroneous refusal to search for the key AND the key having a TTL that has not passed yet.

Since there are now two entries with the same key inside when apc_exists is used, it gets confused and freezes.

Takeaways: Do not store flags on APC and always have a backup case prepared in case it misses. APC seems to work best when used only to store copies of material that exists elsewhere (i.e. a file or record in a database).

+5
source

I believe this is not mentioned explicitly, but deadlocks occur only with the apc_exists function. apc_fetch does not seem to suffer. I found that changing apc_store for apc_add does not affect deadlocks, they occur for both functions.

Validating an existing one with apc_fetch might look like this:

 public function has($key) { apc_fetch($key, $exists); return $exists; } 
+1
source

All Articles