framework icon indicating copy to clipboard operation
framework copied to clipboard

MySQL connect timeout exceeded should result in a re-connect, but it does not

Open GrahamCampbell opened this issue 2 years ago • 4 comments

Laravel Version

10.27.0

PHP Version

8.1.11

Database Driver & Version

MySQL

Description

The DB connector code is meant to retry failed connections, but failing to connect due to a connect timeout is not retried. I have observed this on MySQL, but possibly other drivers suffer the same issue.

Steps To Reproduce

Using the mysql driver, set the host to google.com. Only one attempt is made to connect to the DB because tryAgainIfCausedByLostConnection determines that message SQLSTATE[HY000] [2002] Operation timed out should not be re-tried. I think the tryAgainIfCausedByLostConnection logic is great for re-connecting post-connect, but is not so good for retrying the initial connect. I think we need to add additional message matching specifically for the connector code, only. A timeout should not otherwise be retried, since that could result in double inserts, for example.

GrahamCampbell avatar Oct 10 '23 11:10 GrahamCampbell

Thank you for reporting this issue!

As Laravel is an open source project, we rely on the community to help us diagnose and fix issues as it is not possible to research and fix every issue reported to us via GitHub.

If possible, please make a pull request fixing the issue you have described, along with corresponding tests. All pull requests are promptly reviewed by the Laravel team.

Thank you!

github-actions[bot] avatar Oct 10 '23 12:10 github-actions[bot]

This is interesting and simple in original concept, but comes with some caviats.

These issues may be ignorable in original draft when getting review on concept, but I think should be thought out (or accounted for) in the final PR.

I hope these don't prevent anyone from contributing, but instead just allows someone to be able to tackle it knowing some of the edge cases.

Wrinkles that add to the complexity:

  • Database transactions build up a state, if the connection goes away, that state is purged. A reconnection would not have this state.
  • Database variables if set will not persist on a reconnection. These are not currently handled within Laravel itself, so would be difficult to track currently.
  • Temp Tables are temporary tables that are selected into. These are connection dependent, so once a connection is dropped, they go away. They are not supported directly by Laravel, so are difficult to track currently.

Possible solutions:

Database Transactions

Currently Laravel tracks these, so it like the insert counter, we could rely on a counter for that.

Database Variables

We could either add first class support for these, and thus make them more trackable (like a counter). Or we can say that since they are not first class citizens, they should not be used at all.

Temp Tables

At least in my experience these are rarely used. Ignoring these could be somewhat safe, but may more mean this behavior needs to be more configurable?

Dealing with more than one wrinkle at once

Maybe mark the connection as not reconnnectable once any raw query is issued.

kassah avatar Nov 28 '23 21:11 kassah

Closing this issue because it's inactive, already solved, old or not relevant anymore. Feel to open up a new issue if you're still experiencing this.

driesvints avatar Jan 05 '24 14:01 driesvints

Is not solved and is still relevant.

GrahamCampbell avatar Jan 05 '24 14:01 GrahamCampbell

@GrahamCampbell going to close this one now as it's been open for too long. Seems we haven't gotten other reports about this. If you want, we'd still accept a PR, thanks.

driesvints avatar Jun 03 '24 12:06 driesvints