简体   繁体   中英

MongoDb error: cannot use 'j' option when a host does not have journaling enabled

I was using mongo in dev just fine, when deploying the app into test env I got this error when objects are saved in the application

cannot use 'j' option when a host does not have journaling enabled


Dispatcher servlet is the same for both applications (dev vs test) with JOURNAL_SAFE
What did I do wrong?

    <mongo:mongo host="127.0.0.1" port="27017" write-concern="JOURNAL_SAFE">
    <mongo:options connections-per-host="50"
               threads-allowed-to-block-for-connection-multiplier="4"
               connect-timeout="1000"
               max-wait-time="1500"
               auto-connect-retry="true"
               socket-keep-alive="true"
               socket-timeout="1500"
               slave-ok="true"
               write-number="1"
               write-timeout="0"
               write-fsync="false"/>
</mongo:mongo>

Full stack trace:

Caused by: com.mongodb.CommandFailureException: { "serverUsed" : "127.0.0.1:27017" , "ok" : 0 , "code" : 2 , "errmsg" : "cannot use 'j' option when a host does not have journaling enabled"} 
    at com.mongodb.CommandResult.getException(CommandResult.java:76) 
    at com.mongodb.CommandResult.throwOnError(CommandResult.java:131) 
    at com.mongodb.DBCollectionImpl$3.execute(DBCollectionImpl.java:498) 
    at com.mongodb.DBCollectionImpl$3.execute(DBCollectionImpl.java:491) 
    at com.mongodb.DBTCPConnector.doOperation(DBTCPConnector.java:210) 
    at com.mongodb.DBCollectionImpl.receiveWriteCommandMessage(DBCollectionImpl.java:491) 
    at com.mongodb.DBCollectionImpl.writeWithCommandProtocol(DBCollectionImpl.java:430) 
    at com.mongodb.DBCollectionImpl.updateWithCommandProtocol(DBCollectionImpl.java:417) 
    at com.mongodb.DBCollectionImpl.update(DBCollectionImpl.java:267) 
    at com.mongodb.DBCollection.update(DBCollection.java:191) 
    at com.mongodb.DBCollection.update(DBCollection.java:224) 
    at com.xerox.dao.MainDaoImpl.saveOrUpdatePrinter(MainDaoImpl.java:246) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
    at java.lang.reflect.Method.invoke(Method.java:606) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) 
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155) 
    ... 44 more

This was a change in 2.6. The MongoDB server now requires that journaling be enabled to use a write concern that has journaling as a requirement. In 2.4 and before the server would silently ignore the journal requirement is journaling was not enabled on the server.

You test MongoDB cluster must have journaling disabled. Either enable journaling on the server or remove the default write concern on the client (eg, remove/change write-concern="JOURNAL_SAFE"). For production, you almost definitely want journaling enabled.

If you are using a replica set (or a shared cluster of replica sets) with at least 3 data holding members then a write concern of 'majority' might be a better, more performant, choice. (eg, write-concern="MAJORITY" ).

If you are running a single Mongod process that is not part of a replica-set then you probably want a journal write concern but need to make sure that the journal is not disabled on the server. If you cannot control the server (and are still using a single mongod process) then you might want to switch to the FSYNC write concern. With FSYNC if the server has journaling enabled then it acts as a Journaled write, for a server without journaling enabled it will force all of the data files to disk (which will cause a lot of latency). Having said that you are better off getting journaling enabled on the server.

Rob.

I am posting this here in hopes someone else will find this helpful since it helped me.

I wanted to run mongock for production purposes but it kept failing all my unit tests.

I kept getting the following error:

Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'connectionDriver' defined in class path resource [io/mongock/driver/mongodb/springdata/v3/config/SpringDataMongoV3Context.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [io.mongock.driver.api.driver.ConnectionDriver]: Factory method 'connectionDriver' threw exception; nested exception is com.mongodb.MongoCommandException: Command failed with error 2 (BadValue): 'cannot use 'j' option when a host does not have journaling enabled' on server localhost:52663. The full response is {"ok": 0.0, "errmsg": "cannot use 'j' option when a host does not have journaling enabled", "code": 2, "codeName": "BadValue"}

The solution was to add this flag in the application-test.properties:

mongock.enabled=false

For the one using Spring Boot, I would avoid deactivating mongock because your mongo db is not sync with prod anymore.

You can create your own EmbeddedMongoAutoConfiguration and add the journal in it.

Personally, I used this one with Spring Boot 2.7:

@Configuration
public class MyEmbeddedMongoConfiguration extends EmbeddedMongoAutoConfiguration {

    private final MongoProperties properties;

    private static final byte[] IP4_LOOPBACK_ADDRESS = new byte[]{127, 0, 0, 1};
    private static final byte[] IP6_LOOPBACK_ADDRESS = new byte[]{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};

    public MyEmbeddedMongoConfiguration(MongoProperties properties) {
        super(properties);
        this.properties=properties;
    }

    @Bean
    public MongodConfig embeddedMongoConfiguration(EmbeddedMongoProperties embeddedProperties) throws IOException {
        ImmutableMongodConfig.Builder builder = MongodConfig.builder()
                .version(Version.V4_0_12)
                .cmdOptions(MongoCmdOptions.builder().useNoJournal(false).build());
        EmbeddedMongoProperties.Storage storage = embeddedProperties.getStorage();
        if (storage != null) {
            String databaseDir = storage.getDatabaseDir();
            String replSetName = storage.getReplSetName();
            int oplogSize = storage.getOplogSize() != null ? (int)storage.getOplogSize().toMegabytes() : 0;
            builder.replication(new de.flapdoodle.embed.mongo.config.Storage(databaseDir, replSetName, oplogSize));
        }

        Integer configuredPort = this.properties.getPort();
        if (configuredPort != null && configuredPort > 0) {
            builder.net(new Net(this.getHost().getHostAddress(), configuredPort, Network.localhostIsIPv6()));
        } else {
            builder.net(new Net(this.getHost().getHostAddress(), Network.freeServerPort(this.getHost()), Network.localhostIsIPv6()));
        }

        return builder.build();
    }

    private InetAddress getHost() throws UnknownHostException {
        return this.properties.getHost() == null ? InetAddress.getByAddress(Network.localhostIsIPv6() ? IP6_LOOPBACK_ADDRESS : IP4_LOOPBACK_ADDRESS) : InetAddress.getByName(this.properties.getHost());
    }
}

The important part:

  ImmutableMongodConfig.Builder builder = MongodConfig.builder()
                .version(Version.V4_0_12).cmdOptions(MongoCmdOptions.builder().useNoJournal(false).build());

This code is adapted from the Spring Boot Configuration EmbeddedMongoAutoConfiguration . Look for the method embeddedMongoConfiguration if you need to do it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM