Skip to content
This repository has been archived by the owner. It is now read-only.

feat(mysql): Ensure db connections always run in strict mode. #221

Merged
merged 1 commit into from Jan 5, 2017

Conversation

@rfk
Copy link
Member

@rfk rfk commented Nov 14, 2016

This was an idea I had to enforce mysql strict mode and utf8mb4 on all db connections. It's possible (and advisable!) to set these defaults in the MySQL server itself, but we can also enforce them here as an additional layer of protection.

No tests yet, because we don't have any test infra for mocking out MySQL in this repo.

@jrgm @vladikoff thoughts?

// Enforce sane defaults on every new connection.
// These *should* be set by the database by default, but it's nice
// to have an additional layer of protection here.
this._pool.on('connection', function(connection) {

This comment has been minimized.

@rfk

rfk Nov 14, 2016
Author Member

In theory the overhead of doing this won't be too bad, because we only do it when we create a new connection for the pool, and we then re-use that connection for many queries.

One downside of doing this by listening to an event though, is that we can't block until the query has been completed. So there'd probably be a race condition here, where calling code could use the connection in between the SELECT @@sql_mode and the SET SESSION sql_mode.

This comment has been minimized.

@seanmonstar

seanmonstar Nov 14, 2016
Member

To prevent this race condition, this code could exist in the _getConnection method down below. It can then only resolve the connection once this query has completed, and done.

This comment has been minimized.

@rfk

rfk Nov 14, 2016
Author Member

It wasn't obvious to me whether all the various helper methods used _getConnection though, it looks like e.g. _query() just directly takes a connection from the pool. Is _getConnection intended to replace the pool's default connection-getting logic uniformly?

This comment has been minimized.

@seanmonstar

seanmonstar Nov 14, 2016
Member

Oh interesting. It seems we could make use of _getConnection inside _query, and then yes, we can be sure the session is always set correctly.

Currently, it looks like _getConnection was written so that we can release the connection after using it, but that in most cases we just use pool.query which keeps the connection internal and thus we never worry about releasing it.

This comment has been minimized.

@rfk

rfk Nov 14, 2016
Author Member

Also, ISTM that doing this logic in _getConnection would cause it to be run on every query, while using the pool event means it runs only when we create a new connection.

This comment has been minimized.

@seanmonstar

seanmonstar Nov 15, 2016
Member

We could set a flag, like connection._fxa_strict = true, to only do it once per connection.

This comment has been minimized.

@vladikoff

vladikoff Nov 24, 2016
Contributor

👍


function MysqlStore(options) {
if (options.charset && options.charset !== 'UTF8_UNICODE_CI') {
logger.warn('createDatabase', { charset: options.charset });
if (options.charset && options.charset !== 'UTF8MB4_UNICODE_CI') {

This comment has been minimized.

@vladikoff

vladikoff Nov 24, 2016
Contributor

nit: extract 'UTF8MB4_UNICODE_CI' into const REQUIRED_CHARSET = ...;

@vladikoff
Copy link
Contributor

@vladikoff vladikoff commented Nov 24, 2016

@jrgm any other feedback?

@rfk rfk force-pushed the mysql-strict-mode branch from c1ec9f1 to 80fde65 Jan 3, 2017
@rfk rfk force-pushed the mysql-strict-mode branch from 80fde65 to f8dffdc Jan 3, 2017
@rfk
Copy link
Member Author

@rfk rfk commented Jan 3, 2017

I've updated this based on discussion, and added some simple tests. @seanmonstar r?

Copy link
Member

@seanmonstar seanmonstar left a comment

Looks clean to me, great!

'STRICT_ALL_TABLES',
'NO_ENGINE_SUBSTITUTION',
];
const REQUIRED_CHARSET = 'UTF8MB4_UNICODE_CI';

This comment has been minimized.

@seanmonstar

seanmonstar Jan 5, 2017
Member

Yay moving to const.

@rfk
Copy link
Member Author

@rfk rfk commented Jan 5, 2017

@jrgm per discussion in the meeting, the implications of strict mode are described here:

http://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sql-mode-strict

I don't see anything to worry about in there, and TBH if we are doing something that's affected by strict mode, I consider it a bug we need to uncover and fix ASAP. This works well in travis and my local testing, so I'm going to optimistically merge it and keep an eye on behaviour in latest.

@rfk rfk merged commit b10b88c into master Jan 5, 2017
3 checks passed
3 checks passed
ci/circleci Your tests passed on CircleCI!
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
continuous-integration/travis-ci/push The Travis CI build passed
Details
@rfk rfk removed the waffle:review label Jan 5, 2017
@rfk rfk added this to the FxA-0: quality milestone Jan 25, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

5 participants