Skip to content

Commit

Permalink
Add support for transaction access mode (vitessio#11704)
Browse files Browse the repository at this point in the history
* feat: added transaction access mode to proto

Signed-off-by: Harshit Gangal <[email protected]>

* refactor: tx_pool create transaction code

Signed-off-by: Harshit Gangal <[email protected]>

* feat: use tx access mode in vttablet and set that when starting a transaction

Signed-off-by: Harshit Gangal <[email protected]>

* feat: reset transaction access mode after commit/rollback/release

Signed-off-by: Harshit Gangal <[email protected]>

* feat: added parsing support for start transaction with characteristics

Signed-off-by: Harshit Gangal <[email protected]>

* feat: set the transaction characteristics in execute option on start transaction statement

Signed-off-by: Harshit Gangal <[email protected]>

* refactor: little tx_pool refactor

Signed-off-by: Harshit Gangal <[email protected]>

* test: added e2e test for tx access modes

Signed-off-by: Harshit Gangal <[email protected]>

* added release notes

Signed-off-by: Harshit Gangal <[email protected]>

* addressed review comments

Signed-off-by: Harshit Gangal <[email protected]>

* generated protobuf files updated

Signed-off-by: Harshit Gangal <[email protected]>

Signed-off-by: Harshit Gangal <[email protected]>
  • Loading branch information
harshit-gangal authored Nov 23, 2022
1 parent 4f850f6 commit a5099a9
Show file tree
Hide file tree
Showing 28 changed files with 9,924 additions and 9,041 deletions.
34 changes: 34 additions & 0 deletions doc/releasenotes/16_0_0_summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,37 @@ is now fixed. The full issue can be found [here](https://github.com/vitessio/vit
### Deprecations

The V3 planner is deprecated as of the V16 release, and will be removed in the V17 release of Vitess.

### MySQL Compatibility

#### Transaction Isolation Level
Support added for `set [session] transaction isolation level <transaction_characteristic>`
```sql
transaction_characteristic: {
ISOLATION LEVEL level
| access_mode
}

level: {
REPEATABLE READ
| READ COMMITTED
| READ UNCOMMITTED
| SERIALIZABLE
}
```
This will set the transaction isolation level for the current session.
This will be applied to any shard where the session will open a transaction.

#### Transaction Access Mode
Support added for `start transaction` with transaction characteristic.
```sql
START TRANSACTION
[transaction_characteristic [, transaction_characteristic] ...]

transaction_characteristic: {
WITH CONSISTENT SNAPSHOT
| READ WRITE
| READ ONLY
}
```
This will allow users to start a transaction with these characteristics.
Original file line number Diff line number Diff line change
Expand Up @@ -174,3 +174,56 @@ func TestTransactionIsolation(t *testing.T) {
utils.AssertMatches(t, conn1, "select id, msg from test where id = 1", `[[INT64(1) VARCHAR("foo")]]`)
utils.Exec(t, conn1, "rollback")
}

func TestTransactionAccessModes(t *testing.T) {
closer := start(t)
defer closer()

ctx := context.Background()

conn, err := mysql.Connect(ctx, &vtParams)
require.NoError(t, err)
defer conn.Close()

// start a transaction with read-only characteristic.
utils.Exec(t, conn, "start transaction read only")
_, err = utils.ExecAllowError(t, conn, "insert into test(id, msg) values (42,'foo')")
require.Error(t, err)
require.Contains(t, err.Error(), "Cannot execute statement in a READ ONLY transaction")
utils.Exec(t, conn, "rollback")

// trying autocommit, this should pass as transaction characteristics are limited to single transaction.
utils.Exec(t, conn, "insert into test(id, msg) values (42,'foo')")

// target replica
utils.Exec(t, conn, "use `ks@replica`")
// start a transaction with read-only characteristic.
utils.Exec(t, conn, "start transaction read only")
utils.Exec(t, conn, "select * from test")

// start a transaction with read-write characteristic. This should fail
utils.Exec(t, conn, "start transaction read write")
_, err = utils.ExecAllowError(t, conn, "select connection_id()")
require.Error(t, err)
require.Contains(t, err.Error(), "cannot start read write transaction on a read only tablet")
utils.Exec(t, conn, "rollback")
}

func start(t *testing.T) func() {
deleteAll := func() {
conn, err := mysql.Connect(context.Background(), &vtParams)
require.NoError(t, err)
tables := []string{"test", "twopc_user"}
for _, table := range tables {
_, _ = utils.ExecAllowError(t, conn, "delete from "+table)
}
conn.Close()
}

deleteAll()

return func() {
deleteAll()
cluster.PanicHandler(t)
}
}
1,884 changes: 978 additions & 906 deletions go/vt/proto/query/query.pb.go

Large diffs are not rendered by default.

97 changes: 97 additions & 0 deletions go/vt/proto/query/query_vtproto.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion go/vt/sqlparser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -562,8 +562,13 @@ type (
DBName IdentifierCS
}

// TxAccessMode is an enum for Transaction Access Mode
TxAccessMode int8

// Begin represents a Begin statement.
Begin struct{}
Begin struct {
TxAccessModes []TxAccessMode
}

// Commit represents a Commit statement.
Commit struct{}
Expand Down
11 changes: 11 additions & 0 deletions go/vt/sqlparser/ast_clone.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion go/vt/sqlparser/ast_equals.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 13 additions & 1 deletion go/vt/sqlparser/ast_format.go
Original file line number Diff line number Diff line change
Expand Up @@ -963,7 +963,19 @@ func (node *Commit) Format(buf *TrackedBuffer) {

// Format formats the node.
func (node *Begin) Format(buf *TrackedBuffer) {
buf.literal("begin")
if node.TxAccessModes == nil {
buf.literal("begin")
return
}
buf.literal("start transaction")
for idx, accessMode := range node.TxAccessModes {
if idx == 0 {
buf.astPrintf(node, " %s", accessMode.ToString())
continue
}
buf.astPrintf(node, ", %s", accessMode.ToString())
}

}

// Format formats the node.
Expand Down
16 changes: 15 additions & 1 deletion go/vt/sqlparser/ast_format_fast.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions go/vt/sqlparser/ast_funcs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1895,6 +1895,20 @@ func (columnFormat ColumnFormat) ToString() string {
}
}

// ToString returns the TxAccessMode type as a string
func (ty TxAccessMode) ToString() string {
switch ty {
case WithConsistentSnapshot:
return WithConsistentSnapshotStr
case ReadWrite:
return ReadWriteStr
case ReadOnly:
return ReadOnlyStr
default:
return "Unknown Transaction Access Mode"
}
}

// CompliantName is used to get the name of the bind variable to use for this column name
func (node *ColName) CompliantName() string {
if !node.Qualifier.IsEmpty() {
Expand Down
14 changes: 14 additions & 0 deletions go/vt/sqlparser/cached_size.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions go/vt/sqlparser/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,11 @@ const (
RepeatableReadStr = "repeatable-read"
SerializableStr = "serializable"

// Transaction access mode
WithConsistentSnapshotStr = "with consistent snapshot"
ReadWriteStr = "read write"
ReadOnlyStr = "read only"

// Explain formats
EmptyStr = ""
TreeStr = "tree"
Expand Down Expand Up @@ -859,3 +864,10 @@ const (
IntervalMinuteMicrosecond
IntervalSecondMicrosecond
)

// Transaction access mode
const (
WithConsistentSnapshot TxAccessMode = iota
ReadWrite
ReadOnly
)
Loading

0 comments on commit a5099a9

Please sign in to comment.