forked from MaterializeInc/materialize
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
coord: Optimize single statement read transaction (MaterializeInc#15255)
The PostgreSQL extended wire protocol (https://www.postgresql.org/docs/current/protocol-flow.html#PROTOCOL-FLOW-EXT-QUERY) leaves it ambiguous as to whether or not the current statement will be single statement implicit transaction or a multi statement implicit transaction. Due to this ambiguity, we previously removed all of our single statement read transactions in a887755. This ended up negatively impacting query freshness and latency in the Serializable isolation level. PostgreSQL will eagerly commit implicit transactions after executing certain statements but before receiving a Sync message. See https://www.postgresql.org/message-id/flat/17434-d9f7a064ce2a88a3%40postgresql.org and https://git.postgresql.org/gitweb/?p=postgresql.git&a=commitdiff&h=f92944137. This commit will eagerly commit ALL statements in an implicit transaction when using the extended protocol. This vastly simplifies things and allows us to re-apply the optimizations we previously made to single statement transactions. Multi-statement implicit transactions using the extended protocol are extremely rare and an edge case. They are not possible unless a client uses pipelining in psql or a custom driver. The PostgreSQL BEGIN documentation even wrongly implies that they don't exist (https://www.postgresql.org/docs/current/sql-begin.html). Therefore, it's much better to apply the optimizations in the common case than to allow this edge case feature. Much of this commit is reversing certain parts of a887755. Fixes #14696 Fixes #14038
- Loading branch information
Showing
17 changed files
with
347 additions
and
151 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
# Test that multiple DDL statements in the same extended request are supported | ||
send | ||
Parse {"query": "CREATE TABLE a (a int)"} | ||
Bind | ||
Execute | ||
Parse {"query": "CREATE TABLE b (a int)"} | ||
Bind | ||
Execute | ||
Parse {"query": "INSERT INTO a VALUES (1)"} | ||
Bind | ||
Execute | ||
Parse {"query": "SELECT 1/0"} | ||
Bind | ||
Execute | ||
Sync | ||
Query {"query": "SELECT * FROM a"} | ||
---- | ||
|
||
until | ||
ReadyForQuery | ||
ReadyForQuery | ||
---- | ||
ParseComplete | ||
BindComplete | ||
CommandComplete {"tag":"CREATE TABLE"} | ||
ParseComplete | ||
BindComplete | ||
CommandComplete {"tag":"CREATE TABLE"} | ||
ParseComplete | ||
BindComplete | ||
CommandComplete {"tag":"INSERT 0 1"} | ||
ParseComplete | ||
BindComplete | ||
ErrorResponse {"fields":[{"typ":"S","value":"ERROR"},{"typ":"C","value":"XX000"},{"typ":"M","value":"division by zero"}]} | ||
ReadyForQuery {"status":"I"} | ||
RowDescription {"fields":[{"name":"a"}]} | ||
DataRow {"fields":["1"]} | ||
CommandComplete {"tag":"SELECT 1"} | ||
ReadyForQuery {"status":"I"} | ||
|
||
send | ||
Parse {"query": "SELECT * FROM a"} | ||
Bind | ||
Execute | ||
Sync | ||
---- | ||
|
||
until | ||
ReadyForQuery | ||
---- | ||
ParseComplete | ||
BindComplete | ||
DataRow {"fields":["1"]} | ||
CommandComplete {"tag":"SELECT 1"} | ||
ReadyForQuery {"status":"I"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
# In Materialize we eagerly commint implicit transactions after Execute | ||
# messages, causing portals to be destroyed. | ||
send | ||
Parse {"query": "VALUES (1), (2)"} | ||
Bind {"portal": "c"} | ||
Execute {"portal": "c", "max_rows": 1} | ||
Execute {"portal": "c", "max_rows": 1} | ||
Sync | ||
---- | ||
|
||
until | ||
ReadyForQuery | ||
---- | ||
ParseComplete | ||
BindComplete | ||
DataRow {"fields":["1"]} | ||
PortalSuspended | ||
ErrorResponse {"fields":[{"typ":"S","value":"ERROR"},{"typ":"C","value":"34000"},{"typ":"M","value":"portal \"c\" does not exist"}]} | ||
ReadyForQuery {"status":"I"} | ||
|
||
# Verify that portals (cursors) are destroyed on Execute. | ||
send | ||
Parse {"query": "VALUES (1), (2)"} | ||
Bind {"portal": "c"} | ||
Execute {"portal": "c", "max_rows": 1} | ||
Sync | ||
Query {"query": "FETCH c"} | ||
---- | ||
|
||
until | ||
ReadyForQuery | ||
ReadyForQuery | ||
---- | ||
ParseComplete | ||
BindComplete | ||
DataRow {"fields":["1"]} | ||
PortalSuspended | ||
ReadyForQuery {"status":"I"} | ||
ErrorResponse {"fields":[{"typ":"S","value":"ERROR"},{"typ":"C","value":"34000"},{"typ":"M","value":"cursor \"c\" does not exist"}]} | ||
ReadyForQuery {"status":"I"} |
Oops, something went wrong.