MyCATApache/Mycat-Server · critical · RuntimeException

can't fetch sequnce in db,sequnce

Error message

can't fetch sequnce in db,sequnce :{seqName} detail:{lastestError}

What it means

IncrSequenceMySQLHandler.getSeqValueFromDB delegates to SequenceVal.fetchSequenceFromDB to load the next sequence segment from MySQL; a single thread enters with retry logic built in. If the fetch still returns null after retries, the handler throws this RuntimeException, appending the sequence name and the last recorded error from the MySQL fetcher. It means MyCat could not obtain a new ID segment from the database and cannot hand out IDs.

Solutions

  1. Inspect the detail appended in the message (mysqlSeqFetcher.getLastestError) and fix the root cause — typically connectivity, credentials, or SQL errors against the sequence DB.
  2. Verify the sequence table and the row for seqName exist and are readable by MyCat's configured sequence datasource.
  3. Restore/restart the MySQL backend and check network/firewall between MyCat and the DB, then retry ID generation.
  4. Monitor DB load and tune timeouts/retries so transient lock waits don't exhaust the fetch attempts.

Example fix

// before
long id = handler.nextId("ORDER_SEQ"); // RuntimeException: can't fetch sequnce in db
// after
-- on the sequence DB: ensure definition exists and is reachable
SELECT * FROM MYCAT_SEQUENCE WHERE name = 'ORDER_SEQ';
GRANT SELECT, UPDATE ON mycat.* TO 'mycat_seq_user'@'%';
Defensive patterns

Strategy: retry

Validate before calling

public static boolean canFetchSequence(DataSource ds, String seqName) {
    try (Connection c = ds.getConnection(); PreparedStatement ps =
            c.prepareStatement("SELECT current_value, increment FROM MYCAT_SEQUENCE WHERE name = ?")) {
        ps.setString(1, seqName);
        try (ResultSet rs = ps.executeQuery()) { return rs.next(); }
    } catch (SQLException e) { return false; }
}

Try / catch

try {
    long id = handler.nextId(seqName);
} catch (RuntimeException e) {
    if (e.getMessage() != null && e.getMessage().startsWith("can't fetch sequnce in db")) {
        if (!canFetchSequence(seqDataSource, seqName)) {
            throw new SequenceBackendUnavailableException(seqName, e); // fail fast, don't hot-loop
        }
        return handler.nextId(seqName); // backend healthy again: bounded retry
    }
    throw e;
}

Prevention

When it happens

Trigger: Calling nextId (directly or via getNextValidSeqVal or recursion) when fetchSequenceFromDB(mysqlSeqFetcher, 1, true) returns null — i.e. the SELECT on the sequence table repeatedly fails (connection error, missing table, lock timeout, malformed sequence row).

Common situations: MySQL backend for sequences down or unreachable from MyCat; MYCAT_SEQUENCE table missing/dropped or row deleted; insufficient DB privileges for the MyCat sequence user; network timeouts under load exhausting the built-in retries.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


AI-assisted analysis of MyCATApache/Mycat-Server@65f8d8beb7 (2026-09-11). Data as JSON: /api/errors/b3fcb83a6f802f7e. Report an issue: GitHub.

Appendix: source

Thrown at src/main/java/io/mycat/route/sequence/handler/IncrSequenceMySQLHandler.java:143

			LOGGER.debug("get next segement of sequence from db for sequnce:"
					+ seqVal.seqName + " curVal " + seqVal.curVal);
		}
		//设置正在获取
		boolean isLock = seqVal.fetching.compareAndSet(false, true);
		if(isLock) {
			//判断当前的是否有效。
			if(seqVal.successFetched == true) {
				Long nexVal = seqVal.nextValue();
				if (seqVal.isNexValValid(nexVal)) {
					seqVal.fetching.compareAndSet(true, false);
					return nexVal;
				}
			}
						
			//发起请求sql 等待到返回  或者进行
			Long[] values = seqVal.fetchSequenceFromDB( mysqlSeqFetcher, 1, true); //只有一个线程可以进 并且有重试机制。
			if (values == null) {
				throw new RuntimeException("can't fetch sequnce in db,sequnce :"
						+ seqVal.seqName + " detail:"
						+ mysqlSeqFetcher.getLastestError(seqVal.seqName));
			} else {
					seqVal.setCurValue(values[0]); 
					seqVal.maxSegValue = values[1];
					seqVal.successFetched = true; //设置successFetched
					return values[0];
			
			}
		} else {
			long count = 0 ;
			//正在获取 ,或者还未返回
			while(seqVal.fetching.get() || seqVal.successFetched == false){
				try {										
					Thread.sleep(10);
					if(++count > 10000L) {
						return this.getSeqValueFromDB(seqVal);
					}

View on GitHub (pinned to 65f8d8beb7)