@@ -205,7 +205,7 @@ public Mono<Void> beginTransaction() {
205205
206206 @ Override
207207 public Mono <Void > beginTransaction (TransactionDefinition definition ) {
208- return Mono .defer (() -> QueryFlow .beginTransaction (client , this , batchSupported , definition ));
208+ return Mono .defer (() -> QueryFlow .beginTransaction (client , this , batchSupported , definition , context ));
209209 }
210210
211211 @ Override
@@ -306,8 +306,8 @@ public MySqlConnectionMetadata getMetadata() {
306306 }
307307
308308 /**
309- * MySQL does not have any way to query the isolation level of the current transaction, only inferred from
310- * past statements, so driver can not make sure the result is right.
309+ * MySQL does not have any way to query the isolation level of the current transaction, only inferred from past
310+ * statements, so driver can not make sure the result is right.
311311 * <p>
312312 * See <a href="https://bugs.mysql.com/bug.php?id=53341">MySQL Bug 53341</a>
313313 * <p>
@@ -424,6 +424,11 @@ public boolean isInTransaction() {
424424 public Mono <Void > setLockWaitTimeout (Duration timeout ) {
425425 requireNonNull (timeout , "timeout must not be null" );
426426
427+ if (!context .isLockWaitTimeoutSupported ()) {
428+ logger .warn ("Lock wait timeout is not supported by server, setLockWaitTimeout operation is ignored" );
429+ return Mono .empty ();
430+ }
431+
427432 long timeoutSeconds = timeout .getSeconds ();
428433 return QueryFlow .executeVoid (client , "SET innodb_lock_wait_timeout=" + timeoutSeconds )
429434 .doOnSuccess (ignored -> this .lockWaitTimeout = this .currentLockWaitTimeout = timeoutSeconds );
@@ -484,13 +489,20 @@ static Mono<MySqlConnection> init(
484489 ) {
485490 Mono <MySqlConnection > connection = initSessionVariables (client , sessionVariables )
486491 .then (loadSessionVariables (client , codecs , context ))
492+ .flatMap (data -> loadInnoDbEngineStatus (data , client , codecs , context ))
487493 .map (data -> {
488494 ZoneId timeZone = data .timeZone ;
489495 if (timeZone != null ) {
490496 logger .debug ("Got server time zone {} from loading session variables" , timeZone );
491497 context .setTimeZone (timeZone );
492498 }
493499
500+ if (data .lockWaitTimeoutSupported ) {
501+ context .enableLockWaitTimeoutSupported ();
502+ } else {
503+ logger .info ("Lock wait timeout is not supported by server, all related operations will be ignored" );
504+ }
505+
494506 return new MySqlSimpleConnection (client , context , codecs , data .level , data .lockWaitTimeout ,
495507 queryCache , prepareCache , data .product , prepare );
496508 });
@@ -534,10 +546,10 @@ private static Mono<Void> initSessionVariables(Client client, List<String> sessi
534546 private static Mono <SessionData > loadSessionVariables (
535547 Client client , Codecs codecs , ConnectionContext context
536548 ) {
537- StringBuilder query = new StringBuilder (160 )
549+ StringBuilder query = new StringBuilder (128 )
538550 .append ("SELECT " )
539551 .append (transactionIsolationColumn (context ))
540- .append (",@@innodb_lock_wait_timeout AS l,@@ version_comment AS v" );
552+ .append (",@@version_comment AS v" );
541553
542554 Function <MySqlResult , Flux <SessionData >> handler ;
543555
@@ -554,6 +566,24 @@ private static Mono<SessionData> loadSessionVariables(
554566 .last ();
555567 }
556568
569+ private static Mono <SessionData > loadInnoDbEngineStatus (
570+ SessionData data , Client client , Codecs codecs , ConnectionContext context
571+ ) {
572+ return new TextSimpleStatement (client , codecs , context ,
573+ "SHOW VARIABLES LIKE 'innodb\\ \\ _lock\\ \\ _wait\\ \\ _timeout'" )
574+ .execute ()
575+ .flatMap (r -> r .map (readable -> {
576+ String value = readable .get (1 , String .class );
577+
578+ if (value == null || value .isEmpty ()) {
579+ return data ;
580+ } else {
581+ return data .lockWaitTimeout (Long .parseLong (value ));
582+ }
583+ }))
584+ .single (data );
585+ }
586+
557587 private static Mono <Void > initDatabase (Client client , String database ) {
558588 return client .exchange (new InitDbMessage (database ), INIT_DB )
559589 .last ()
@@ -572,16 +602,15 @@ private static Mono<Void> initDatabase(Client client, String database) {
572602 private static Flux <SessionData > convertSessionData (MySqlResult r , boolean timeZone ) {
573603 return r .map (readable -> {
574604 IsolationLevel level = convertIsolationLevel (readable .get (0 , String .class ));
575- long lockWaitTimeout = convertLockWaitTimeout (readable .get (1 , Long .class ));
576- String product = readable .get (2 , String .class );
605+ String product = readable .get (1 , String .class );
577606
578- return new SessionData (level , lockWaitTimeout , product , timeZone ? readZoneId (readable ) : null );
607+ return new SessionData (level , product , timeZone ? readZoneId (readable ) : null );
579608 });
580609 }
581610
582611 private static ZoneId readZoneId (Readable readable ) {
583- String systemTimeZone = readable .get (3 , String .class );
584- String timeZone = readable .get (4 , String .class );
612+ String systemTimeZone = readable .get (2 , String .class );
613+ String timeZone = readable .get (3 , String .class );
585614
586615 if (timeZone == null || timeZone .isEmpty () || "SYSTEM" .equalsIgnoreCase (timeZone )) {
587616 if (systemTimeZone == null || systemTimeZone .isEmpty ()) {
@@ -628,24 +657,13 @@ private static IsolationLevel convertIsolationLevel(@Nullable String name) {
628657 return IsolationLevel .REPEATABLE_READ ;
629658 }
630659
631- private static long convertLockWaitTimeout (@ Nullable Long timeout ) {
632- if (timeout == null ) {
633- logger .error ("Lock wait timeout is null, fallback to " + DEFAULT_LOCK_WAIT_TIMEOUT + " seconds" );
634-
635- return DEFAULT_LOCK_WAIT_TIMEOUT ;
636- }
637-
638- return timeout ;
639- }
640-
641660 /**
642- * Resolves the column of session isolation level, the {@literal @@tx_isolation} has been marked as
643- * deprecated.
661+ * Resolves the column of session isolation level, the {@literal @@tx_isolation} has been marked as deprecated.
644662 * <p>
645663 * If server is MariaDB, {@literal @@transaction_isolation} is used starting from {@literal 11.1.1}.
646664 * <p>
647- * If the server is MySQL, use {@literal @@transaction_isolation} starting from {@literal 8.0.3}, or
648- * between {@literal 5.7.20} and {@literal 8.0.0} (exclusive).
665+ * If the server is MySQL, use {@literal @@transaction_isolation} starting from {@literal 8.0.3}, or between
666+ * {@literal 5.7.20} and {@literal 8.0.0} (exclusive).
649667 */
650668 private static String transactionIsolationColumn (ConnectionContext context ) {
651669 ServerVersion version = context .getServerVersion ();
@@ -664,20 +682,26 @@ private static final class SessionData {
664682
665683 private final IsolationLevel level ;
666684
667- private final long lockWaitTimeout ;
668-
669685 @ Nullable
670686 private final String product ;
671687
672688 @ Nullable
673689 private final ZoneId timeZone ;
674690
675- private SessionData (IsolationLevel level , long lockWaitTimeout , @ Nullable String product ,
676- @ Nullable ZoneId timeZone ) {
691+ private long lockWaitTimeout = -1 ;
692+
693+ private boolean lockWaitTimeoutSupported ;
694+
695+ private SessionData (IsolationLevel level , @ Nullable String product , @ Nullable ZoneId timeZone ) {
677696 this .level = level ;
678- this .lockWaitTimeout = lockWaitTimeout ;
679697 this .product = product ;
680698 this .timeZone = timeZone ;
681699 }
700+
701+ SessionData lockWaitTimeout (long timeout ) {
702+ this .lockWaitTimeoutSupported = true ;
703+ this .lockWaitTimeout = timeout ;
704+ return this ;
705+ }
682706 }
683707}
0 commit comments