This is an automated email from the ASF dual-hosted git repository. JackieTien97 pushed a commit to branch rc/2.0.11 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit 945af2a1e95cea4efd361409c5c664b94162ade1 Author: shuwenwei <[email protected]> AuthorDate: Tue Aug 4 12:21:03 2026 +0800 Fix IndexOutOfBoundsException caused by concurrent sort and delete on TVList (#18389) --- .../db/utils/datastructure/AlignedTVList.java | 31 +++++++++++++++++++--- .../iotdb/db/utils/datastructure/TVList.java | 8 +++++- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java index 068b4f0cc06..33713d0c16f 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/AlignedTVList.java @@ -652,7 +652,13 @@ public abstract class AlignedTVList extends TVList { } @Override - public int delete(long lowerBound, long upperBound) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized int delete(long lowerBound, long upperBound) { int deletedNumber = 0; for (int i = 0; i < dataTypes.size(); i++) { deletedNumber += delete(lowerBound, upperBound, i).left; @@ -660,7 +666,13 @@ public abstract class AlignedTVList extends TVList { return deletedNumber; } - public int deleteTime(long lowerBound, long upperBound) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized int deleteTime(long lowerBound, long upperBound) { delete(lowerBound, upperBound); int prevDeletedCnt = this.timeDeletedCnt; for (int i = 0; i < rowCount; i++) { @@ -703,12 +715,17 @@ public abstract class AlignedTVList extends TVList { /** * Delete points in a specific column. * + * <p>Must be synchronized with {@link #sort()} on the same TVList instance: a query may sort this + * list in place ({@code sort()} is synchronized), and a concurrent delete would otherwise read + * the half-rebuilt {@code indices} and throw IndexOutOfBoundsException or delete wrong rows. + * * @param lowerBound deletion lower bound * @param upperBound deletion upper bound * @param columnIndex column index to be deleted * @return Delete info pair. Left: deletedNumber int; right: ifDeleteColumn boolean */ - public Pair<Integer, Boolean> delete(long lowerBound, long upperBound, int columnIndex) { + public synchronized Pair<Integer, Boolean> delete( + long lowerBound, long upperBound, int columnIndex) { if (columnIndex >= values.size()) { return new Pair<>(0, false); } @@ -731,7 +748,13 @@ public abstract class AlignedTVList extends TVList { return new Pair<>(deletedNumber, deleteColumn); } - public void deleteColumn(int columnIndex) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized void deleteColumn(int columnIndex) { if (bitMaps == null) { List<List<BitMap>> localBitMaps = new ArrayList<>(dataTypes.size()); for (int j = 0; j < dataTypes.size(); j++) { diff --git a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java index 3141ad3c8b4..9dbd11cf626 100644 --- a/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java +++ b/iotdb-core/datanode/src/main/java/org/apache/iotdb/db/utils/datastructure/TVList.java @@ -580,7 +580,13 @@ public abstract class TVList implements WALEntryValue { return clone(); } - public int delete(long lowerBound, long upperBound) { + /* + * Must be synchronized with sort() on the same TVList instance: a query may sort + * this list in place (sort() is synchronized), and a concurrent delete would + * otherwise read the half-rebuilt indices and throw IndexOutOfBoundsException + * or delete wrong rows. + */ + public synchronized int delete(long lowerBound, long upperBound) { int deletedNumber = 0; long maxTime = Long.MIN_VALUE; long minTime = Long.MAX_VALUE;
