Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

race condition when sqlite database is created #626

Closed
mbiebl opened this issue Jul 2, 2018 · 20 comments
Closed

race condition when sqlite database is created #626

mbiebl opened this issue Jul 2, 2018 · 20 comments

Comments

@mbiebl
Copy link
Contributor

mbiebl commented Jul 2, 2018

Version: 7.0.1

I'm using phpfastcache with php 7.2 under IIS/Windows Server 2016 using php in CGI mode.
The backend is sqlite.

If the sqlite database does not exist yet, and I have multiple clients access the server at the same time, there seems to be a race condition when the database is created, as I get the following in the php error log:

[02-Jul-2018 17:58:28 UTC] PHP Fatal error:  Uncaught ErrorException: mkdir(): File exists in C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php:107
Stack trace:
#0 [internal function]: exception_error_handler(2, 'mkdir(): File e...', 'C:\\src\\Gal2Go-s...', 107, Array)
#1 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php(107): mkdir('C:\\Windows\\TEMP...', 511, true)
#2 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Drivers\Sqlite\Driver.php(74): Phpfastcache\Drivers\Sqlite\Driver->getPath()
#3 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Drivers\Sqlite\Driver.php(82): Phpfastcache\Drivers\Sqlite\Driver->getSqliteDir()
#4 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\DriverBaseTrait.php(70): Phpfastcache\Drivers\Sqlite\Driver->driverCheck()
#5 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastc in C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php on line 107
@Geolim4
Copy link
Member

Geolim4 commented Jul 2, 2018 via email

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 2, 2018

I certainly feel like this is a bug.It's not a problem of sqlite itself, but how the sqlite db is created in the first place.
Fwiw, I've also tried the files backend, and it was even worse in that regard.

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 2, 2018

as for ssdb, its upstream authors do not recommend to run it on windows.
memcache(d) is not really an option on Windows either.
redis proved to perform really badly with all the overhead caused by the HTTP based API.

@Geolim4
Copy link
Member

Geolim4 commented Jul 2, 2018 via email

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 2, 2018

again, it's not about sqlite itself behaving badly with concurrent access.
It's about how the sqlite db is created initially.

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 2, 2018

Regarding the files backend, I've just reran the tests:

[02-Jul-2018 23:38:50 UTC] PHP Fatal error:  Uncaught ErrorException: mkdir(): File exists in C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php:107
Stack trace:
#0 [internal function]: exception_error_handler(2, 'mkdir(): File e...', 'C:\\src\\Gal2Go-s...', 107, Array)
#1 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php(107): mkdir('C:\\Windows\\TEMP...', 511, true)
#2 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Drivers\Files\Driver.php(59): Phpfastcache\Drivers\Files\Driver->getPath()
#3 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\DriverBaseTrait.php(70): Phpfastcache\Drivers\Files\Driver->driverCheck()
#4 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Drivers\Files\Driver.php(51): Phpfastcache\Drivers\Files\Driver->__parentConstruct(Object(Phpfastcache\Drivers\Files\Config), '1921810a5f544cc...')
#5 C:\src\Gal2Go in C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php on line 107
[02-Jul-2018 23:38:50 UTC] PHP Fatal error:  Uncaught ErrorException: mkdir(): File exists in C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php:107
Stack trace:
#0 [internal function]: exception_error_handler(2, 'mkdir(): File e...', 'C:\\src\\Gal2Go-s...', 107, Array)
#1 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php(107): mkdir('C:\\Windows\\TEMP...', 511, true)
#2 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Drivers\Files\Driver.php(59): Phpfastcache\Drivers\Files\Driver->getPath()
#3 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\DriverBaseTrait.php(70): Phpfastcache\Drivers\Files\Driver->driverCheck()
#4 C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Drivers\Files\Driver.php(51): Phpfastcache\Drivers\Files\Driver->__parentConstruct(Object(Phpfastcache\Drivers\Files\Config), '1921810a5f544cc...')
#5 C:\src\Gal2Go in C:\src\Gal2Go-server\localhost\vendor\phpfastcache\phpfastcache\lib\Phpfastcache\Core\Pool\IO\IOHelperTrait.php on line 107

So it seems to suffer from a similar issue. Turning on secureFileManipulation didn't help

@Geolim4
Copy link
Member

Geolim4 commented Jul 2, 2018

I'm not gently sliding to trolling, but Windows & PHP environment are not know to be very friendly since many extension are not even supported or simply not updated since a while (Memcache, Xcache, APC, etc).

It looks like you're option-limited and since you looks like developing locally, I'm advising you to use some Vagrant/Docker VM to run your app under Unix env which would save you further nightmare not only about Phpfastcache.

The problem with Sqlite is that the creation of the database cannot be concurrent since we're on a unique binary file unlike every else backend drivers :/

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 2, 2018

Have you seen the response regarding the Files backend? It seems to have the same problem.
And yes, I'm restricted to the Windows Plattform/IIS for running this particular application and docker etc is not really an option here.
Nothing so far really indicates though that this is really a problem which is specific to Windows though.

@Geolim4
Copy link
Member

Geolim4 commented Jul 2, 2018

What can I say: You are the first reporting me this issue after 3 major release, some users I know are using it on highly sensitive productions, I'm myself using the Files driver on a million visitor per month website (with an average of 10~15Mo/s rw I/O), and a couple of API apps and this kind of error never appeared once on my side.

If you can identity some issue I would be glad and thankful but actually, at this point, I'm completely unable to reproduce your case.

@Geolim4
Copy link
Member

Geolim4 commented Jul 3, 2018

I just ran 10 tests in the exact same time in my company using 10000 items each and no errors appeared using Files driver (On a Win10x64 computer). Sqlite succeeded too despite its horrible time-spend. Honestly I'm not sure how to reproduce your issue ATM, at least give me a code sample or open a pull request if you identified the potential cause.

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 3, 2018

I think the key to reproduce the problem is to remove the cache files, then start multiple clients at once (in my case I use a jmeter test which simulates 500 concurrent users with no ramp up time).

@Geolim4
Copy link
Member

Geolim4 commented Jul 3, 2018

Obviously if you run 500 concurrent requests in the exact same time (which is very unlikely, even with 1M visitor/month this never happened) you are clearly looking for troubles ;)

In your case indeed there's no way on my level to fix that bug even by putting some kind of .tmp file to queue the requests because even the .tmp file would be overridden.

Your case clearly suggest me to encourage your to move to a stronger cache backend that handle concurrency far better than Sqlite.

Redis/SSdb are doing perfectly the job as much are Cassandra, Couchdb and Couchbase are doing it.

@Geolim4
Copy link
Member

Geolim4 commented Jul 3, 2018

The whole list of supported backends ATM is available below:
https://github.com/PHPSocialNetwork/phpfastcache/wiki#supported-drivers-at-this-day-

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 3, 2018

Well, a fix for that would be to create a lock which is released once the db is created

@Geolim4
Copy link
Member

Geolim4 commented Jul 3, 2018

Yes but all your concurrent requests would create the lock in the same time. Making the fix useless :/

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 3, 2018

You try to acquire a lock and you are blocked if it's already taken. Only one can take it, not all of them.

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 3, 2018

@Geolim4
Copy link
Member

Geolim4 commented Jul 3, 2018

Well, a lock is not reliable at all since some system put the lock at the process-level and not at the thread-level. Php being frequently configured in a fcgi mode this would not be reliable...

@mbiebl
Copy link
Contributor Author

mbiebl commented Jul 4, 2018

Obviously if you run 500 concurrent requests in the exact same time (which is very unlikely, even with 1M visitor/month this never happened) you are clearly looking for troubles ;)

Yeah, the load test was intended to look for trouble or rather problems in our application.
I'll give you that this is an artificial test, having so many concurrent users hit the server immediately without an initialized db. I thought it would be worth filing a bug report anyway, to make phpfastcache more robust in this regard.
Anyway, thanks a lot for your prompt responses and for developing phpfastcache!

@Geolim4
Copy link
Member

Geolim4 commented Jul 5, 2018

I'm usually always trying to improve Phpfastcache performance and efficiency by respecting at least three fundamental rules:

  • The improvement is cross-platform and not targeted on a specific OS/Environment (except in case of degraded condition hotfix on a specific OS/Environment)
  • The improvement does not involve any hackish/dirty patch that make the code unmaintainable for anyone that discover and try to understand the code logic of Phpfastcache
  • The library stays Psr6/16 compliant no matter what, in order to ensure a maximum portability of the library.

Thanks for your report, this is always appreciated even in the case I can't fix it immediately for any reason whatsoever.

Cheers,
Georges.L

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants