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

sql: provide a way to temporarily disable foreign key checks on a session basis #23624

Closed
jordanlewis opened this issue Mar 8, 2018 · 22 comments
Assignees
Labels
A-sql-execution Relating to SQL execution. A-sql-mutations Mutation statements: UPDATE/INSERT/UPSERT/DELETE. C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception)

Comments

@jordanlewis
Copy link
Member

jordanlewis commented Mar 8, 2018

MySQL provides an option SET FOREIGN_KEY_CHECKS=0; which temporarily disables all foreign key checks on a session basis. This would be useful to have in CockroachDB as well.

@jordanlewis jordanlewis added this to the Later milestone Mar 8, 2018
@bdarnell
Copy link
Contributor

bdarnell commented Mar 9, 2018

How does this relate to DEFERRABLE constraints (#9897)?

@dt
Copy link
Member

dt commented Mar 9, 2018

Also curious if the proposed functionality in #19444 meets the same use case.

@dt
Copy link
Member

dt commented Mar 9, 2018

Specifically, if we did add a session setting like this instead of the DISABLE ALL mutation on the tables, I think it should a) require ALTER on the tables it writes to and b) must mark all FKs it ignores as unvalidated, if they’re not already, since it may have invalidated them.

@jordanlewis
Copy link
Member Author

Oops. Dupe of #19444. This came up in context of testing TPCC - it would be nice to be able to disable foreign key checks via a session setting to test performance with and without those checks.

@jordanlewis
Copy link
Member Author

Oh, wait. No, this is specifically about a session setting that evilly skips validating foreign key constraints regardless of the state of the schema.

https://dev.mysql.com/doc/refman/5.7/en/server-system-variables.html#sysvar_foreign_key_checks

Setting foreign_key_checks to 1 does not trigger a scan of the existing table data. Therefore, rows added to the table while foreign_key_checks=0 will not be verified for consistency.

@knz
Copy link
Contributor

knz commented Mar 9, 2018

@jordanlewis can you clarify what the use case is? It sounds a bit like "I want a tool to shoot myself in the foot"

@BramGruneir
Copy link
Member

I don't think this is a good idea. The only use case I can think of is for bulk inserts to existing already partially filled tables.

Mysql has this option because they don't have deferred. But if I recall, when you turn fk checks back on, it doesn't then go perform them all. It just assumes you know what you're doing.

I covered this in https://github.com/cockroachdb/cockroach/blob/master/docs/RFCS/20171201_cascade.md

See the https://github.com/cockroachdb/cockroach/blob/master/docs/RFCS/20171201_cascade.md#survey-of-other-databases for how they all deal with it.

@dt
Copy link
Member

dt commented Mar 9, 2018

I do not think we should implement it exactly as mysql does -- just disabling the check code. I think, if you've chosen to not check FKs at all, we need to record on those FKs that we can no longer make promises about their on-disk data... until you run VALIDATE CONSTRAINT to re-assert that they're okay. I think I still prefer #19444, but, if you wanted a session var to do it on the fly -- which has the advantage that didn't need to figure out on which tables FKs needed to be disabled to run a specific test -- I'd still want it to have the same side-effects as #19444.

@petermattis
Copy link
Collaborator

This issue arose from a desire to temporarily disable the FK checks in order to determine their performance impact. I could be satisfied with an easy way to do this via recompilation. @jordanlewis pointed out that MySQL has a setting for it. I have had this desire, I imagine users might as well. It seems reasonable to make it clear how absolutely dangerous this setting is.

@dt
Copy link
Member

dt commented Mar 9, 2018

👍 it does indeed seem like a not uncommon desire to quantify the cost of checking constraints. To clarify my concern, I'm not opposed to disabling checks, but rather that on that re-enabling them the database should not make potentially false claims.

@petermattis
Copy link
Collaborator

@dt Agreed. Either we need to document that the foreign keys might be invalid, or provide a mechanism for re-validating them.

@dt
Copy link
Member

dt commented Mar 9, 2018

Yep, we have that mechanism for re-validating -- VALIDATE CONSTRAINT -- that can be run on constraints in the UNVALIDATED state, which is when we enforce the constraint on new writes but cannot vouch for it on-disk until validated.

@knz
Copy link
Contributor

knz commented Mar 9, 2018

Related: #23663

you may want to extend the mechanism to also disable CHECK validation

@knz
Copy link
Contributor

knz commented May 14, 2018

Re-thinking this with a cool head, I realize that if any one session would enable the setting to disable FK checks, then FK constraints potentially become invalidated for every other session, not just the one.

For me this 100% turns this feature into a cluster-wide setting.

Also the action of changing the setting from "on" (no FK checks) back to "off" (FK checks enabled) should edit all the table descriptors to mark constraints as UNVALIDATED.

@knz
Copy link
Contributor

knz commented May 14, 2018

Also, should a client violate the FK constraints, this means the table stats would go out of whack, and the query optimizer would subsequently start to make very bad choices.

@knz
Copy link
Contributor

knz commented May 14, 2018

(I'm overall 👎 on this feature due to the disorderly spill of invalidity)

@knz knz added C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception) A-sql-execution Relating to SQL execution. labels May 14, 2018
@knz
Copy link
Contributor

knz commented May 14, 2018

Anyone who further looks into this please carefully envision the interaction with a user who mistakenly sets this and starts (unintendedly) corrupting their database.

How would you explain this user how to put their database back into a valid state? How do you suggest they identify which writes were violating their FK constraints? How do you suggest they go back in history to fix/remove these writes (made with the setting enabled) and no other (made with the setting disabled)?

@knz
Copy link
Contributor

knz commented May 14, 2018

The UX story here in the "bad case" is so supremely horrendous that it makes me shudder.

Perhaps we should requalify this issue to become a build flag instead.

@dt
Copy link
Member

dt commented May 14, 2018

@knz fwiw, I think it also makes sense to consider #19444 as an alternative -- disabling the FKs themselves in the schema via a schema change command. That makes it readily apparent that they're disabled to all observers, unlike per-session state, and has clear semantics for what happens after: re-enabling them is done explicitly, via a followup schema change, and can include (perhaps with an option) re-validation of them.

@knz
Copy link
Contributor

knz commented May 14, 2018

Yes #19444 sounds much saner to me.

@knz knz added the A-sql-mutations Mutation statements: UPDATE/INSERT/UPSERT/DELETE. label Sep 21, 2018
@petermattis petermattis removed this from the Later milestone Oct 5, 2018
@dt
Copy link
Member

dt commented Oct 31, 2018

I think we should close this, and if we want the ability to disable constraints checking, pursue the approach in #19444.

I still think #19444 is a safer, less foot-gun solution to the underlying desire to temporarily disable constraints for performance reasons, but given that constraints are making promises about the table data, recording that they're disabled on the table seems much safer to me than just in one client's in-memory session.

@knz
Copy link
Contributor

knz commented Jan 2, 2019

agreed

@knz knz closed this as completed Jan 2, 2019
willbryant added a commit to willbryant/kitchen_sync that referenced this issue Apr 7, 2020
…or a cockroachdb fork, to support writes at least

* sql_ascii hopefully unnecessary (not even completely sure it's important for postgresql).
* there's no equivalent to pg_relation_size etc.
* there's no way to disable FK constraints (cockroachdb/cockroach#23624, closed in favor of cockroachdb/cockroach#19444 which wouldn't suit)

to support reads, we'd also need to write out pg_export_snapshot().
* cockroachdb would use AS OF SYSTEM TIME ..., but it's hard to choose the value.
* we should use statement_timestamp() or the semi-undocumented cluster_logical_timestamp(), but https://forum.cockroachlabs.com/t/use-cockroachdb-cluster-timestamp-in-time-travel-queries/2093/6 says that if you use a value less than --max-offset ago, you may not read your own writes.
* and I can't even see a way to get the max-offset value, in order to workaround by sleeping that long.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-sql-execution Relating to SQL execution. A-sql-mutations Mutation statements: UPDATE/INSERT/UPSERT/DELETE. C-enhancement Solution expected to add code/behavior + preserve backward-compat (pg compat issues are exception)
Projects
None yet
Development

No branches or pull requests

6 participants