Boosting Massive Data Updates in Spring Boot: Manual Transactions, Multithreading, and UNION Batch Tricks

An in‑depth guide shows how to accelerate updating tens of thousands of MySQL rows in a Spring Boot‑MyBatis project by switching from automatic per‑record commits to manual transactions, applying multithreaded execution with CountDownLatch coordination, and using UNION‑based batch updates when native batch support is unavailable.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Boosting Massive Data Updates in Spring Boot: Manual Transactions, Multithreading, and UNION Batch Tricks

Introduction

In a business scenario we need to modify up to 50,000 rows in a MySQL table using Spring Boot and MyBatis, but the system does not support batch or asynchronous updates, so a simple for‑loop is used, which takes too long.

Loop without manual transaction

@Test
void updateStudent() {
    List<Student> allStudents = studentMapper.getAll();
    allStudents.forEach(s -> {
        String teacher = s.getTeacher();
        String newTeacher = "TNO_" + new Random().nextInt(100);
        s.setTeacher(newTeacher);
        studentMapper.update(s);
    });
}

The loop takes about 1 min 54 s because each update is committed automatically.

Adding manual transaction

@Autowired
private DataSourceTransactionManager dataSourceTransactionManager;
@Autowired
private TransactionDefinition transactionDefinition;

@Test
void updateStudentWithTrans() {
    List<Student> allStudents = studentMapper.getAll();
    TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);
    try {
        allStudents.forEach(s -> {
            String newTeacher = "TNO_" + new Random().nextInt(100);
            s.setTeacher(newTeacher);
            studentMapper.update(s);
        });
        dataSourceTransactionManager.commit(transactionStatus);
    } catch (Throwable e) {
        dataSourceTransactionManager.rollback(transactionStatus);
        throw e;
    }
}

Execution time drops to about 24 s, roughly five times faster.

Multithreaded update with CountDownLatch

We wrap the update logic in a service and launch several threads, each handling a partition of the data. A CountDownLatch synchronises the threads and the main thread.

@Test
void updateStudentWithThreads() {
    List<Student> allStudents = studentMapper.getAll();
    int threadCount = 100;
    int dataPartionLength = (allStudents.size() + threadCount - 1) / threadCount;
    ExecutorService pool = Executors.newFixedThreadPool(threadCount);
    CountDownLatch latch = new CountDownLatch(threadCount);
    for (int i = 0; i < threadCount; i++) {
        List<Student> part = allStudents.stream()
                .skip(i * dataPartionLength).limit(dataPartionLength).collect(Collectors.toList());
        pool.execute(() -> {
            studentService.updateStudents(part, latch);
        });
    }
    latch.await(30, TimeUnit.SECONDS);
    System.out.println("Main thread completed");
}

Testing shows the best performance around 2‑5 threads; more threads do not improve speed and may cause connection‑pool exhaustion.

Controlling multithreaded transactions with two CountDownLatch

Each thread starts its own transaction, performs updates, then waits for the main latch before committing or rolling back based on an error flag.

public void updateStudentsThread(List<Student> students,
                                   CountDownLatch threadLatch,
                                   CountDownLatch mainLatch,
                                   StudentTaskError taskStatus) {
    TransactionStatus ts = dataSourceTransactionManager.getTransaction(transactionDefinition);
    try {
        students.forEach(s -> {
            String newTeacher = "TNO_" + new Random().nextInt(100);
            s.setTeacher(newTeacher);
            studentMapper.update(s);
        });
    } catch (Throwable e) {
        taskStatus.setIsError();
    } finally {
        threadLatch.countDown();
    }
    try {
        mainLatch.await();
    } catch (Throwable e) {
        taskStatus.setIsError();
    }
    if (taskStatus.getIsError()) {
        dataSourceTransactionManager.rollback(ts);
    } else {
        dataSourceTransactionManager.commit(ts);
    }
}

Using a collection of TransactionStatus

All thread‑local TransactionStatus objects are stored in a synchronized list; after all threads finish, the main thread commits or rolls back the whole collection.

Batch update via UNION

If the database does not support native batch UPDATE, we can build a derived table with UNION of multiple SELECT statements and join it to the target table.

UPDATE student, (
    (SELECT 1 AS id, 'teacher_A' AS teacher)
    UNION
    (SELECT 2 AS id, 'teacher_A' AS teacher)
    UNION
    (SELECT 3 AS id, 'teacher_A' AS teacher)
    /* …more rows… */
) AS new_teacher
SET student.teacher = new_teacher.teacher
WHERE student.id = new_teacher.id;

Summary

Manual transaction control can dramatically improve bulk update performance.

Multithreading speeds up processing only up to a moderate thread count (2‑5 in the test).

When many threads hold connections, the connection pool may be exhausted, causing timeout errors.

If possible, use true batch UPDATE; otherwise UNION‑based updates are a viable alternative.

Performance chart
Performance chart
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

transactionSpring BootMyBatis
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.