2
我有一個Spring應用程序,當前使用存儲過程執行一些查詢。配置是這樣的:使用ReplicationDriver在mysql slave上調用存儲過程
數據源:
<bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="com.mysql.jdbc.ReplicationDriver"/>
<property name="url" value="jdbc:mysql:replication://master,slave1,slave2/db?allowMultiQueries=true"/>
<property name="username" value="${db.dbusername}"/>
<property name="password" value="${db.dbpassword}"/>
<property name="defaultReadOnly" value="true"/>
</bean>
<bean id="jdbcDeviceDAO" class="dao.jdbc.JdbcDeviceDAO">
<property name="dataSource" ref="dataSource"/>
</bean>
DAO:
public class JdbcDeviceDAO implements DeviceDAO {
// ...
public void setDataSource(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
this.procGetCombinedDeviceRouting = new SimpleJdbcCall(jdbcTemplate)
.withProcedureName("get_combined_device_routing");
// ...
}
public CombinedDeviceRouting getCombinedDeviceRouting(String deviceName, String deviceNameType) {
SqlParameterSource in = createParameters(deviceName, deviceNameType);
Map<String, Object> results = this.procGetCombinedDeviceRouting.execute(in);
return extractResults(results);
}
現在,當我打電話getCombinedDeviceRouting(...),它失敗,出現以下異常:
org.springframework.dao.TransientDataAccessResourceException: CallableStatementCallback; SQL [{call get_combined_device_routing()}]; Connection is read-only. Queries leading to data modification are not allowed; nested exception is java.sql.SQLException: Connection is read-only. Queries leading to data modification are not allowed
我知道連接是隻讀的,我需要它是這樣的,以便查詢在從屬主機之間進行負載平衡。但是存儲過程實際上是隻讀的,它只是很多SELECT語句,實際上我嘗試將READS SQL DATA添加到它的定義中,但它不起作用。
最後,我來到了讀取MySQL的連接器代碼的點,我發現這一點:
protected boolean checkReadOnlySafeStatement() throws SQLException {
synchronized (checkClosed().getConnectionMutex()) {
return this.firstCharOfStmt == 'S' || !this.connection.isReadOnly();
}
}
這聽起來很幼稚,但是是連接器檢查我的發言是否只讀只是匹配的第一個字符'S'? 如果是這種情況,似乎沒有辦法在從屬主機上調用存儲過程,因爲該語句以'C'(CALL ...)開頭。
有沒有人知道是否有解決這個問題的解決方法?或者,也許我錯了,假設第一個字符檢查?