Skip to content

Commit e400950

Browse files
committed
Use pipelining to begin a transaction. Fixes #1286
1 parent 957dd42 commit e400950

File tree

2 files changed

+52
-12
lines changed

2 files changed

+52
-12
lines changed

src/MySqlConnector/Core/ServerSession.cs

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -586,15 +586,13 @@ public async Task<bool> TryResetConnectionAsync(ConnectionSettings cs, MySqlConn
586586
Log.SendingPipelinedResetConnectionRequest(m_logger, Id, ServerVersion.OriginalString);
587587

588588
// send both packets at once
589-
await m_payloadHandler!.ByteHandler.WriteBytesAsync(m_pipelinedResetConnectionBytes!, ioBehavior).ConfigureAwait(false);
589+
await SendRawAsync(m_pipelinedResetConnectionBytes, ioBehavior, cancellationToken).ConfigureAwait(false);
590590

591591
// read two OK replies
592-
m_payloadHandler.SetNextSequenceNumber(1);
593-
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
592+
payload = await ReceiveReplyAsync(1, ioBehavior, cancellationToken).ConfigureAwait(false);
594593
OkPayload.Verify(payload.Span, SupportsDeprecateEof, SupportsSessionTrack);
595594

596-
m_payloadHandler.SetNextSequenceNumber(1);
597-
payload = await ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
595+
payload = await ReceiveReplyAsync(1, ioBehavior, cancellationToken).ConfigureAwait(false);
598596
OkPayload.Verify(payload.Span, SupportsDeprecateEof, SupportsSessionTrack);
599597

600598
return true;
@@ -896,6 +894,12 @@ public async ValueTask<PayloadData> ReceiveReplyAsync(IOBehavior ioBehavior, Can
896894
return payload;
897895
}
898896

897+
public ValueTask<PayloadData> ReceiveReplyAsync(int expectedSequenceNumber, IOBehavior ioBehavior, CancellationToken cancellationToken)
898+
{
899+
m_payloadHandler!.SetNextSequenceNumber(expectedSequenceNumber);
900+
return ReceiveReplyAsync(ioBehavior, cancellationToken);
901+
}
902+
899903
// Continues a conversation with the server by sending a reply to a packet received with 'Receive' or 'ReceiveReply'.
900904
public async ValueTask SendReplyAsync(PayloadData payload, IOBehavior ioBehavior, CancellationToken cancellationToken)
901905
{
@@ -916,6 +920,27 @@ public async ValueTask SendReplyAsync(PayloadData payload, IOBehavior ioBehavior
916920
}
917921
}
918922

923+
// Sends raw bytes over the wire without formatting them into a payload. The caller is expected to set the packet header(s) correctly.
924+
public async ValueTask SendRawAsync(ReadOnlyMemory<byte> data, IOBehavior ioBehavior, CancellationToken cancellationToken)
925+
{
926+
if (CreateExceptionForInvalidState() is { } exception)
927+
{
928+
Log.FailedInSendReplyAsync(m_logger, exception, Id);
929+
throw exception;
930+
}
931+
932+
try
933+
{
934+
// send both packets at once
935+
await m_payloadHandler!.ByteHandler.WriteBytesAsync(data, ioBehavior).ConfigureAwait(false);
936+
}
937+
catch (Exception ex)
938+
{
939+
SetFailed(ex);
940+
throw;
941+
}
942+
}
943+
919944
public static void ThrowIfStatementContainsDelimiter(MySqlException exception, IMySqlCommand command)
920945
{
921946
// check if the command used "DELIMITER"

src/MySqlConnector/MySqlConnection.cs

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -149,16 +149,31 @@ private async ValueTask<MySqlTransaction> BeginTransactionAsync(IsolationLevel i
149149
// get the bytes for both payloads concatenated together (suitable for pipelining)
150150
var startTransactionPayload = GetStartTransactionPayload(isolationLevel, isReadOnly, m_session!.SupportsQueryAttributes);
151151

152-
// send the two packets separately
153-
await m_session.SendAsync(new Protocol.PayloadData(startTransactionPayload.Slice(4, startTransactionPayload.Span[0])), ioBehavior, cancellationToken).ConfigureAwait(false);
152+
if (GetInitializedConnectionSettings() is { UseCompression: false, Pipelining: not false })
153+
{
154+
// send the two packets together
155+
await m_session.SendRawAsync(startTransactionPayload, ioBehavior, cancellationToken).ConfigureAwait(false);
154156

155-
var payload = await m_session.ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
156-
OkPayload.Verify(payload.Span, m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
157+
// read the two OK replies
158+
var payload = await m_session.ReceiveReplyAsync(1, ioBehavior, cancellationToken).ConfigureAwait(false);
159+
OkPayload.Verify(payload.Span, m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
160+
161+
payload = await m_session.ReceiveReplyAsync(1, ioBehavior, cancellationToken).ConfigureAwait(false);
162+
OkPayload.Verify(payload.Span, m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
163+
}
164+
else
165+
{
166+
// send the two packets separately
167+
await m_session.SendAsync(new Protocol.PayloadData(startTransactionPayload.Slice(4, startTransactionPayload.Span[0])), ioBehavior, cancellationToken).ConfigureAwait(false);
157168

158-
await m_session.SendAsync(new Protocol.PayloadData(startTransactionPayload.Slice(8 + startTransactionPayload.Span[0], startTransactionPayload.Span[startTransactionPayload.Span[0] + 4])), ioBehavior, cancellationToken).ConfigureAwait(false);
169+
var payload = await m_session.ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
170+
OkPayload.Verify(payload.Span, m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
159171

160-
payload = await m_session.ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
161-
OkPayload.Verify(payload.Span, m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
172+
await m_session.SendAsync(new Protocol.PayloadData(startTransactionPayload.Slice(8 + startTransactionPayload.Span[0], startTransactionPayload.Span[startTransactionPayload.Span[0] + 4])), ioBehavior, cancellationToken).ConfigureAwait(false);
173+
174+
payload = await m_session.ReceiveReplyAsync(ioBehavior, cancellationToken).ConfigureAwait(false);
175+
OkPayload.Verify(payload.Span, m_session.SupportsDeprecateEof, m_session.SupportsSessionTrack);
176+
}
162177

163178
var transaction = new MySqlTransaction(this, isolationLevel);
164179
CurrentTransaction = transaction;

0 commit comments

Comments
 (0)