But I'm starting to worry that we need to handle this case without inducing deadlock. Sequelize (a Node JS ORM) has nearly a dozen tests of this type that work fine against MSSQL/MySQL/Postgres/SQLite but deadlock against CockroachDB. It's also very confusing to figure out what's wedged if you accidentally write a test like this. I wasted the better part of an hour once because I thought it was the Go database driver that was deadlocking, not Cockroach.
One idea that comes to mind is to teach a stalled read to eventually abort the write that it gets stalled upon. In this case the write transaction, I think, would be able to refresh its spans and commit. I'm not sure if that's feasible, though. My knowledge of our transaction infrastructure is spotty.
I also wonder if you could move the reader's commit timestamp back in time to before the writer's timestamp. That is, in a read-only transaction, couldn't you commit at any time between the timestamp of the latest piece of data you read and the current time (minus the clock offset)? I'll admit that this sounds like a big can of worms.
--Nikhil
You received this message because you are subscribed to the Google Groups "CockroachDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cockroach-db+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
On Sun, Apr 15, 2018 at 11:52 PM, Nikhil Benesch <ben...@cockroachlabs.com> wrote:But I'm starting to worry that we need to handle this case without inducing deadlock. Sequelize (a Node JS ORM) has nearly a dozen tests of this type that work fine against MSSQL/MySQL/Postgres/SQLite but deadlock against CockroachDB. It's also very confusing to figure out what's wedged if you accidentally write a test like this. I wasted the better part of an hour once because I thought it was the Go database driver that was deadlocking, not Cockroach.This is really about transaction isolation levels, not CockroachDB per se. I believe you'd get the same behavior in other DBs if you increased the isolation level to SERIALIZABLE. The test is (unknowingly) making assumptions about the isolation level.
One idea that comes to mind is to teach a stalled read to eventually abort the write that it gets stalled upon. In this case the write transaction, I think, would be able to refresh its spans and commit. I'm not sure if that's feasible, though. My knowledge of our transaction infrastructure is spotty.Yes, we could consider making the read push the write, now that the cost of pushing a write's timestamp is much less than it used to be. However, it's not free, and if we allowed every read to push any write it encountered then writes would be prone to starvation. We'd need some sort of limitation or heuristic here to not push all the time (and if we did that, could we still make the read push the write quickly or reliably enough to make this test pass?)
I also wonder if you could move the reader's commit timestamp back in time to before the writer's timestamp. That is, in a read-only transaction, couldn't you commit at any time between the timestamp of the latest piece of data you read and the current time (minus the clock offset)? I'll admit that this sounds like a big can of worms.Moving the timestamp backwards is risky because it could violate read-your-writes. In this case the test wants to read the value 1, so it needs to pick a timestamp between the first update's and the pending transaction's. How could the server know that?
On Mon, Apr 16, 2018 at 9:17 AM, Ben Darnell <b...@cockroachlabs.com> wrote:On Sun, Apr 15, 2018 at 11:52 PM, Nikhil Benesch <ben...@cockroachlabs.com> wrote:But I'm starting to worry that we need to handle this case without inducing deadlock. Sequelize (a Node JS ORM) has nearly a dozen tests of this type that work fine against MSSQL/MySQL/Postgres/SQLite but deadlock against CockroachDB. It's also very confusing to figure out what's wedged if you accidentally write a test like this. I wasted the better part of an hour once because I thought it was the Go database driver that was deadlocking, not Cockroach.This is really about transaction isolation levels, not CockroachDB per se. I believe you'd get the same behavior in other DBs if you increased the isolation level to SERIALIZABLE. The test is (unknowingly) making assumptions about the isolation level.I thought so too, but even in SERIALIZABLE mode Postgres is capable of handling this test without blocking or aborting either transaction. I can only assume that Postgres is logically reordering the transactions so that the reader commits before the writer, in which case there's no serializability violation.One idea that comes to mind is to teach a stalled read to eventually abort the write that it gets stalled upon. In this case the write transaction, I think, would be able to refresh its spans and commit. I'm not sure if that's feasible, though. My knowledge of our transaction infrastructure is spotty.Yes, we could consider making the read push the write, now that the cost of pushing a write's timestamp is much less than it used to be. However, it's not free, and if we allowed every read to push any write it encountered then writes would be prone to starvation. We'd need some sort of limitation or heuristic here to not push all the time (and if we did that, could we still make the read push the write quickly or reliably enough to make this test pass?)Yeah, what those heuristics would look like is fuzzy to me too. Is this a road even worth exploring?
I also wonder if you could move the reader's commit timestamp back in time to before the writer's timestamp. That is, in a read-only transaction, couldn't you commit at any time between the timestamp of the latest piece of data you read and the current time (minus the clock offset)? I'll admit that this sounds like a big can of worms.Moving the timestamp backwards is risky because it could violate read-your-writes. In this case the test wants to read the value 1, so it needs to pick a timestamp between the first update's and the pending transaction's. How could the server know that?I'm envisioning that we'd assign the read a timestamp that's earlier than the pending write's timestamp but later than the latest committed write on any key in the read set. (It might not be possible to find such a timestamp if there are other outstanding transactions.) Is there a "clocks don't permit this in distributed systems" problem that I'm not seeing here?
On Mon, Apr 16, 2018 at 9:17 AM, Ben Darnell <b...@cockroachlabs.com> wrote:On Sun, Apr 15, 2018 at 11:52 PM, Nikhil Benesch <ben...@cockroachlabs.com> wrote:But I'm starting to worry that we need to handle this case without inducing deadlock. Sequelize (a Node JS ORM) has nearly a dozen tests of this type that work fine against MSSQL/MySQL/Postgres/SQLite but deadlock against CockroachDB. It's also very confusing to figure out what's wedged if you accidentally write a test like this. I wasted the better part of an hour once because I thought it was the Go database driver that was deadlocking, not Cockroach.This is really about transaction isolation levels, not CockroachDB per se. I believe you'd get the same behavior in other DBs if you increased the isolation level to SERIALIZABLE. The test is (unknowingly) making assumptions about the isolation level.I thought so too, but even in SERIALIZABLE mode Postgres is capable of handling this test without blocking or aborting either transaction. I can only assume that Postgres is logically reordering the transactions so that the reader commits before the writer, in which case there's no serializability violation.
One idea that comes to mind is to teach a stalled read to eventually abort the write that it gets stalled upon. In this case the write transaction, I think, would be able to refresh its spans and commit. I'm not sure if that's feasible, though. My knowledge of our transaction infrastructure is spotty.Yes, we could consider making the read push the write, now that the cost of pushing a write's timestamp is much less than it used to be. However, it's not free, and if we allowed every read to push any write it encountered then writes would be prone to starvation. We'd need some sort of limitation or heuristic here to not push all the time (and if we did that, could we still make the read push the write quickly or reliably enough to make this test pass?)Yeah, what those heuristics would look like is fuzzy to me too. Is this a road even worth exploring?I also wonder if you could move the reader's commit timestamp back in time to before the writer's timestamp. That is, in a read-only transaction, couldn't you commit at any time between the timestamp of the latest piece of data you read and the current time (minus the clock offset)? I'll admit that this sounds like a big can of worms.Moving the timestamp backwards is risky because it could violate read-your-writes. In this case the test wants to read the value 1, so it needs to pick a timestamp between the first update's and the pending transaction's. How could the server know that?I'm envisioning that we'd assign the read a timestamp that's earlier than the pending write's timestamp but later than the latest committed write on any key in the read set. (It might not be possible to find such a timestamp if there are other outstanding transactions.) Is there a "clocks don't permit this in distributed systems" problem that I'm not seeing here?
--
--
You received this message because you are subscribed to the Google Groups "CockroachDB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to cockroach-db...@googlegroups.com.