看了下mysql-connector-5.1.40版本中,如果设置failoverReadOnly=true (即默认值,参考链接),当mysql连接failover时,会根据jdbc连接串将当前连接的readOnly值设置为true (第8行代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
private synchronized void switchCurrentConnectionTo( int hostIndex, MySQLConnection connection) throws SQLException { invalidateCurrentConnection(); boolean readOnly; if (isPrimaryHostIndex(hostIndex)) { readOnly = this .explicitlyReadOnly == null ? false : this .explicitlyReadOnly; } else if ( this .failoverReadOnly) { readOnly = true ; } else if ( this .explicitlyReadOnly != null ) { readOnly = this .explicitlyReadOnly; } else if ( this .currentConnection != null ) { readOnly = this .currentConnection.isReadOnly(); } else { readOnly = false ; } syncSessionState( this .currentConnection, connection, readOnly); this .currentConnection = connection; this .currentHostIndex = hostIndex; } |
当执行update操作时,如果检测到readonly,就会跑出createSQLException (第8-9行代码)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
protected int executeUpdate( byte [][] batchedParameterStrings, InputStream[] batchedParameterStreams, boolean [] batchedIsStream, int [] batchedStreamLengths, boolean [] batchedIsNull, boolean isReallyBatch) throws SQLException { synchronized (checkClosed().getConnectionMutex()) { MySQLConnection locallyScopedConn = this .connection; if (locallyScopedConn.isReadOnly()) { throw SQLError.createSQLException(Messages.getString( "PreparedStatement.34" ) + Messages.getString( "PreparedStatement.35" ), SQLError.SQL_STATE_ILLEGAL_ARGUMENT, getExceptionInterceptor()); } .... } } |
上述报错信息是PreparedStatement.34和PreparedStatement.35,查mysql connector的LocalizedErrorMessages.properties
1
2
|
PreparedStatement. 34 =Connection is read-only. PreparedStatement. 35 =Queries leading to data modification are not allowed |
报错信息一致。
因此, 如果是使用的主备mysql,需要手动切换master和slave,如果使用的是多主的mysql(例如,phxsql),需要设置failoverReadOnly=false