Skip to content

Check liveness in PDO_ODBC #6805

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

Closed
wants to merge 4 commits into from

Conversation

NattyNarwhal
Copy link
Member

PDO drivers allow for it, and procedural ODBC has its own facility for it, but PDO_ODBC doesn't. If a connection is severed (for example, on IBM i, ending a database job, or killing the network connection elsewhere), a persistent connection could get stuck. This adapts the procedural ODBC code to PDO for handling connection liveness, so PDO can reconnect if needed.

A discussion about the method to check liveness is linked; this might not be the best method, but it's what procedural ODBC uses, so it's consistent.

PDO drivers allow for it, and procedural ODBC has its own facility
for it, but PDO_ODBC doesn't. If a connection is severed (for example,
on IBM i, ending a databse job, or killing the network connection
elsewhere), a persistent connection could get stuck. This adapts the
procedural ODBC code to PDO for handling connection liveness, so PDO
can reconnect if needed.

A discussion about the method to check liveness is linked; this might
not be the best method, but it's what procedural ODBC uses, so it's
consistent.
@NattyNarwhal
Copy link
Member Author

FWIW, I also have backport patches for 7.4 and 8.0; just related to zend_result and the ABI expansion in 8.1.


/*
* XXX: Should we be using SQL_ATTR_CONNECTION_DEAD? Procedural ODBC
* uses this check, but it might be problematic per #20298
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we should check for SQL_ATTR_CONNECTION_DEAD. ext/odbc likely doesn't do this, because SQLGetConnectAttr () is ODBC 3.0 and the ODBC 2.0 SQLGetConnectOption() doesn't support this attribute, but ext/odbc is still supposed to work with ODBC 2.0 (something we probably should have changed years ago). ext/pdo_odbc requires ODBC 3.0 anyway.

@NattyNarwhal
Copy link
Member Author

Switching it the connection attribute, though I do notice that's actually an ODBC 3.5 thing, and MS offers an additional SQL_COPT_SS_CONNECTION_DEAD...

Not as throughly tested; I'll see if the db2i ODBC driver works, at least.

*/
ret = SQLGetInfo(H->dbc, SQL_DATA_SOURCE_READ_ONLY, d_name,
sizeof(d_name), &len);
/* ODBC 3.5; procedural ODBC uses SQLGetInfo read only instead */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, you're right, SQL_ATTR_CONNECTION_DEAD is ODBC 3.5. We may need a fallback for ODBC 3.0 (maybe just not checking the liveliness there is okay).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm not having much luck with the Db2i driver on Linux; it reconnects, but dead returns both SQL_SUCCESS and dead == 0 (SQL_CD_FALSE). (And a segfault at the end, but I can only assume that might be my fault for running bleeding-edge Fedora.) I can try it on i directly too, but it's the same codebase on both.

If drivers can't report their dead status reliably, maybe using SQLGetInfo only or to verify if the driver is correct would work.

@cmb69
Copy link
Member

cmb69 commented Mar 26, 2021

FWIW, I also have backport patches for 7.4 and 8.0; […]

Not sure which version this should target; it's somewhere between a bugfix and a new feature.

[…] and MS offers an additional SQL_COPT_SS_CONNECTION_DEAD...

Not sure if we should support that; the recommended PDO driver for SQLServer is http://pecl.php.net/pdo_sqlsrv anyway.

@NattyNarwhal
Copy link
Member Author

OK, it's crashing on debian oldstable without my patches applied, so I'm chalking that up to a db2i driver bug on Linux. 🤨 I'll see how the dead attr works on i. If it's as unreliable...

@NattyNarwhal
Copy link
Member Author

Come to think of it, it might even be a leak in PHP now that I have --enable-debug on in these Linux builds. I'll need to triage it more and I don't want to get too side-tracked.

@NattyNarwhal
Copy link
Member Author

So far:

  • Testing on i, with attr dead it doesn't seem to actually reconnect. Rolling back to the SQLGetInfo version worked.
  • On Linux, after rebasing to master, I get the same leak+crash. I might need to report this one onto bugs.php.

@NattyNarwhal
Copy link
Member Author

The Linux issue is probably separate and filed as #80909.

Using the dead attr in the liveness check is ODBC >=3.5 and doesn't
seem to work reliably across drivers; for example, the IBM i Access
driver seems to have issues with it.
@NattyNarwhal
Copy link
Member Author

I rolled back the dead attr check; I don't think it's reliable or well supported enough to rely on. Maybe with a fallback, but then you'd add more possible round trips and increase the cost of persistent connection checks...

@nikic
Copy link
Member

nikic commented Apr 13, 2021

CI failures were unrelated.

@nikic
Copy link
Member

nikic commented Apr 26, 2021

This looks reasonable to me. @cmb69 Any further comments?

Copy link
Member

@cmb69 cmb69 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me now!

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

Successfully merging this pull request may close these issues.

3 participants