-
Notifications
You must be signed in to change notification settings - Fork 3.8k
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: primary keys cannot be changed #19141
Comments
/cc @awoods187 for triage |
@benesch, Do you mean we should support SQL syntax like:
Or just change the primary key of table We should change the data organization when we try to change the primary key of the specified table, this operation's overhead is quite expensive:
|
@a6802739 I mean we should support arbitrary primary key changes like
Since changing a table's primary key is such an expensive operation, we definitely don't want to do it implicitly if the partitioning scheme specifies columns that are not in the primary key. Much rather error in that case, and let the user alter the pkey only if they so choose. Note that traditionally changing the pkey on a table with an existing pkey has required two steps:
That's going to be needlessly expensive in Cockroach. Dropping the primary key requires creating a hidden
My preference would be to eventually support all three, but start by supporting just option one. Options two and three are better for compatibility, but changing a table's primary key probably isn't something you want to lean on your ORM for. Option three has some pathological edge cases FWIW:
@jordanlewis @vivekmenezes @danhhz @knz @cockroachdb/sql-async does this sound reasonable? |
Yes it's reasonable but @a6802739 please do not underestimate the complexity of the task! As much as possible, please split the work in small steps that can be easily reviewed. It might be beneficial that you study the problem and write down your implementation plan before you start (and perhaps share it with us). |
I meant to write "reasonable" in my previous comment. |
@knz, I will first try to understand what should I do for this task, and then write down how to implement it. Maybe I will have some confusion in this process, hope could get some help then. Thank you very much. |
@a6802739 Thank you, as always, for your help. I've discussed this project with the team, and because other high-priority projects with upcoming deadlines rely on this feature, we'll need to develop this feature internally. |
assigned to @danhhz to make sure this finds a good home |
Has there been any thought on how this would be implemented? Changing the primary key is difficult because it is stored in indexes. One thought is that we make a copy of all of the secondary indexes and backfill both them and the new primary index and afterwards delete the old secondary indexes and primary index. Seems like that would conceptually work, though it would be slow. @mjibson, @danhhz, @vivekmenezes Thoughts? |
It depends on whether there's a requirement for this to happen online. If it needs to be online, which is what @benesch's first suggestion implies (
If it doesn't have to be online, then perhaps that first step of "dropping the primary key" could effectively just put the table into read only mode until a new primary key is added, at which point we could perform the backfills above without having to do the table descriptor double write path dance. |
I'd be sad if changing a table's primary key took the table offline. That said, it would still a big improvement over our current "just dump it to CSV and reimport it!" recommendation. |
I've been assuming that any schema change needs to be asynchronous. Let's not lower this bar yet. |
We talked about this yesterday briefly, but just one data point from a customer who wanted to change column types generally (not just primary keys) -> okay with this locking up a table while the change is going on. I don't fully understand the term backfilling, but are we also using this term to describe the faster process we've been talking about re doing something with sstables (vague because I only get 20% of it)? If not, I wonder if someone would want a fast, but offline primary key swap versus a slow but online primary key swap. |
I'm not sure I believe this. Well, I believe the customer has stated that locking the table is ok, but we've also heard many times that async schema changes massively reduce operational burden. |
I think you're right - it's definitely 100x better to have async schema changes. That being said, if one takes way way longer than the other, perhaps it changes our decision? Either way, this is obviously an engineering decision, but just wanted to provide that single relevant data point here. |
I think this is a low impact high effort issue. This change is valuable to a customer who is
I think number 4 in particular is rare. I'll also bring up that when we do this we need to first refactor the codebase to accommodate this change (it should be clear that the code can be modifying two tables). It's very easy to make this change and land up with what we had with the sql executor but this time on the sql DML code paths. I'm just saying that we better think about the weight of this change on the stability of the system and the priority of it for our customers for 2.1. |
I agree that it's high effort, but I think you're understating the impact. We have at least two features where the primary key is crucial (partitioning and interleaving), and even without that people sometimes want to change their primary keys (existing databases all have this feature). It's unrealistic to expect people to be able to choose the correct PK when first creating the table.
If taking the table offline is acceptable, then an export/edit/import process would work. I think if we're going to do this we should do the work to make it async/online.
Changing types of non-PK columns is a separate matter. It's much easier, and I think it's higher priority than changing PKs. |
This item only shows examples where the old primary key is removed first. As outlined in #40771 there's also a scenario possible where a table was defined without a primary key in the first place, and as such nothing was deleted. @jordanlewis I'm perfectly fine with closing the issue I mentioned above. Should this issue also be given the label for postgres compatibility, or would that be counter-effective? |
In CockroachDB a table always has a primary key behind the scenes, so this issue does cover your case as well. Thanks for noticing the missing compat label - I've added it. |
Can this issue be closed once https://www.cockroachlabs.com/docs/v20.1/alter-primary-key.html is stable? |
Yes! In fact, I'm going to go ahead and close this since it will be addressed in 20.1. |
Recently, cockroachdb#35879 and cockroachdb#19141 were closed, so new tests began passing Release justification: non-productrion change Release note: None
46625: kv/kvserver: don't bump ReadTimestamp on EndTxn batch with bounded read latches r=nvanbenschoten a=nvanbenschoten This commit prevents an error-prone situation where requests with an EndTxn request that acquire read-latches at bounded timestamps were allowed to move their ReadTimestamp to their WriteTimestamp without re-acquiring new latches. This could allow the request to read at an unprotected timestamp and forgo proper synchronization with writes with respect to its lock-table scan and timestamp cache update. This relates to 11bffb2, which made a similar fix to server-side refreshes, but not to this new (as of this release) pre-emptive ReadTimestamp update mechanism. This bug was triggering the following assertion when stressing `TestKVNemesisSingleNode`: ``` F200326 15:56:11.350743 1199 kv/kvserver/concurrency/concurrency_manager.go:261 [n1,s1,r33/1:/{Table/50/"60…-Max}] caller violated contract: discovered non-conflicting lock ``` The batch that hit this issue looked like: ``` Get [/Table/50/"a1036fd0",/Min), Get [/Table/50/"e54a51a8",/Min), QueryIntent [/Table/50/"aafccb40",/Min), QueryIntent [/Table/50/"be7f37c9",/Min), EndTxn(commit:true tsflex:true) ``` This commit adds two subtests to `TestTxnCoordSenderRetries` that create this scenario. Release note (bug fix): A rare bug causing an assertion failure was fixed. The assertion error message was "caller violated contract: discovered non-conflicting lock". Release justification: fixes a series bug that could crash a server. Additionally, the bug could have theoretically allowed isolation violations between transactions without hitting the assertion, though this was never observed in practice. cc. @danhhz 46636: roachtest: update blacklists after new fixes r=rafiss a=rafiss Recently, #35879 and #19141 were closed, so new tests began passing Release justification: non-productrion change Release note: None 46732: build: disable required release justifications r=jordanlewis a=otan release-20.1 is cut. Release note: None 46733: licenses: Update BSL change date for master/20.2 r=bdarnell a=otan Release note: None Release justification: N/A Co-authored-by: Nathan VanBenschoten <[email protected]> Co-authored-by: Rafi Shamim <[email protected]> Co-authored-by: Oliver Tan <[email protected]>
It is not currently possible to change a table's primary key, e.g. via
This becomes more important in 1.2 because the upcoming partitioning feature (#18683) will only allow partitioning by prefixes of the primary key. For example, suppose you want to partition this table by country:
The table needs to have a composite primary key that lists country first:
This essentially requires that the schema be designed with partitioning in mind from the get-go until we can alter primary keys.
The text was updated successfully, but these errors were encountered: