WL#12375: xprotocol: reset connection state

Affects: Server-8.0   —   Status: Complete

Motivation

xprotocol supports

  1. Session::Reset
  2. Session::Close
  3. Connection::Close

messages to

  1. reset the current session state without reauth
  2. close the current session and force a reauth, without closing the connection
  3. close the connection

Due to

  • SESS_RESET calls "close current session, force reauth"
  • SESS_CLOSE calls "close current connection"

the implementation in MySQL 8.0.13 and earlier doesn't match the indent behaviour.

Background

Behaviour

The xprotocol defines the behaviour of messages:

session-reset
reset current session (drop temp-tables, session-variables, transactions, ...). Connections stays open and session authenticated.
session-close
close current session. Connection stays open and session needs to authenticated again.
connection-close
close current connection.

Message-IDs

Through ClientMessages::Type they have message-ids and symbolic names assigned:

msg-id client-message name message
6 SESS_RESET Session::Reset
7 SESS_CLOSE Session::Close

Old Client/Old Server (8.0.13) [broken behaviour]

expected client behaviour msg-id server-behaviour
session-reset 6 session-close
session-close 7 connection-close

The 8.0.13 protocol description lists

  • msg-id 6 as SESS_RESET, but the implemented behaviour matches Session::Close.
  • msg-id 7 as SESS_CLOSE, but the implemented behaviour matches Connection::Close.

While the message-name implies one behaviour, the implementation provides another.

It has no way to reset the connections state without having to go through the authentication sequence.

Goal

  • fix invalid behaviour of msg-id 6 in backward compatible way
  • fix invalid hehaviour of msg-id 7 in backward compatible way
  • allow the reset the session state

Design Requirement

DR1
New implementation SHALL NOT be more expensive on the protocol side then working around old, broken behaviour.

Requirements

FR1
New clients MUST be able to reset a session without reauthenticating nor reopening the connection
FR2
New clients MUST be able to close a session without requiring reopening a connection
FR3
Old clients sending a SESS_RESET (msg-id 6) message without payload MUST receive the same behaviour from new servers as they received from old servers: Session::Close
FR4
Old clients sending a SESS_CLOSE (msg-id 7) message without payload MUST receive the same behaviour from new servers as they received from old servers: Connection::Close
FR5
session-reset MUST NOT change the client_id

Implementation

Assumption

  • session-reset behaviour is a subset of session-close behaviour
  • session-close behaviour is a subset of connection-close behaviour

A client asking for session-reset and receiving an Ok, but getting the behaviour session-close, still got the session properly reset.

A client asking for session-close and receiving an Ok, but getting the behaviour connection-close, still got the session closed and left in a state that needs reauthentication. The client can't distinguish if the connection if closed due to wrong server behaviour or very small wait-timeout.

New Client/New Server

expected client-behaviour client msg-id msg-payload server-behaviour
session-close 6 (SESS_RESET) {} session-close
session-reset 6 (SESS_RESET) { keep_open: 1 } session-reset
session-close 7 (SESS_CLOSE) {} session-close

The new implementation does:

  • add a new field to msg-id 6: bool keep_open, default false

    • if keep_open is true
    • the session will be reset (temp-tables droped, user-vars removed, locks removed, transactions rolledback, ...), but stays authenticated.
    • otherwise, the session will be closed and needs to be authenticated again.
    • Important: New clients MUST check if the server supports the new field "keep_open" with an Expect.Open(has_field=6.1).
  • fix the behaviour of msg-id 7 to NOT close the connection immediately anymore.

    • the connection will be closed after mysqlx_wait_timeout

Compatibility

Old Client/New Server

Old clients that send a msg-id 6, assuming session-reset behaviour, will get and Ok and the session is closed. The following statements will fail with "not authenticated" (same as older servers did). The client will report an error to the user. At this time, no client implements behaviour.

Old clients that send msg-id 7, assuming session-close behaviour, will get an Ok and the session gets closed.

expected client-behaviour client msg-id msg-payload server-behaviour
session-close 6 (SESS_RESET) {} session-close
session-close 7 (SESS_CLOSE) {} session-close

New Client/Old Server

New clients that send msg-id 6, assuming session-close behaviour, will get the expected behaviour.

New clients that send msg-id 6 { keep_open: true }, assuming session-reset behaviour, AND check with Expectations that the server support the keep_open field, will get a failed expectation and should fall back to

  • msg-id 6 (session-close)
  • msg-id 4 (session-authenticate-start)

to get the same behaviour.

New clients that send msg-id 7, assuming session-close behaviour, will get connection-close behaviour and need to reopen the connection.

expected client-behaviour client msg-id msg-payload server-behaviour
session-close 6 (SESS_RESET) {} session-close
session-reset 6 (SESS_RESET) { keep_open: 1 } Invalid (1)
session-close 7 (SESS_CLOSE) {} connection-close

(1) client must ask with Expect.Open(has_field=6.1) before use

Notes

"Expectation blocks" are tied to connection, not to the session. This means that Mysqlx.Session.Reset(keep_open:true) must preserve opened expectation blocks.