This is an automated email from the ASF dual-hosted git repository. shuwenwei pushed a commit to branch fix/synchronize-tvlist-delete-with-sort-dev1.3 in repository https://gitbox.apache.org/repos/asf/iotdb.git
commit f3481a315fd10ac144b2a003a5485a1929b69abc Author: shuwenwei <[email protected]> AuthorDate: Tue Aug 4 10:55:00 2026 +0800 Fix IndexOutOfBoundsException caused by concurrent sort and delete on TVList A query may sort the shared working TVList in place while a DELETE is running on the same list. sort() is synchronized, but the delete methods (AlignedTVList.delete/deleteTime/delete(column)/deleteColumn and TVList.delete) were not, so the delete thread could observe the half-rebuilt indices during sort and throw IndexOutOfBoundsException ("Index 0 out of bounds for length 0") or silently delete wrong rows. Synchronize the delete methods with sort() on the same TVList instance, consistent with putAlignedValue/clone/cloneForFlushSort which are already synchronized. The runtime delete path always holds TsFileProcessor.flushQueryLock.writeLock() before touching the TVList, so the lock order (flushQueryLock -> tvlist monitor) stays consistent with the query path and no deadlock is introduced. --- .../db/utils/datastructure/AlignedTVList.java | 23 +++++++++++++++++++--- .../iotdb/db/utils/datastructure/TVList.java | 8 +++++++- 2 files changed, 27 insertions(+), 4 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 9e3a556710c..591c91a6640 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 @@ -539,7 +539,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; @@ -550,12 +556,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); } @@ -577,7 +588,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 d21ecc83e0f..220ca87a9a8 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 @@ -558,7 +558,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;
