欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

shardingJdbc3.x?版本的分頁bug問題解析

 更新時間:2023年06月02日 11:00:03   作者:雨翔河  
這篇文章主要為大家介紹了shardingJdbc3.x?版本的分頁問題解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

引言

shardingJdbc 改名為 shardingsphere ,同時項目也已經(jīng)畢業(yè)并成為 Apache 頂級項目,但是這是發(fā)現(xiàn)它的第二個重大 BUG,說明還是有很大的進步空間。

上次發(fā)現(xiàn)的重大 BUG :http://www.dbjr.com.cn/program/286235e92.htm

BUG 的表象是在使用 shardingJdbc3.1.0 進行分頁查詢的時候存在問題,一般情況下 sql 是這樣的格式 limit x,y ,但是不管怎么翻頁查詢,x 的值一直都是 0,這會導致查詢出來的結(jié)果,每一次翻頁的數(shù)據(jù)會越來越多,都包含了前一頁的數(shù)據(jù)。

首先,使用 shardingJdbc 的情況下,理論上就不應(yīng)該存在分頁查詢。 原因可以想象使用 shardingJdbc 是為了分表,既然是分表了那么這種查詢必然會通過條件查詢所有涉及到的表來得出結(jié)果,然后聚合到內(nèi)存來進行分頁,這會使得機器的壓力是巨大的。

所以如果不涉及到分表的情況下,不應(yīng)該是用 shardingJdbc,如果使用了分表就不應(yīng)該這樣搞分頁查詢。

前提條件是理想的情況下,但是在某些情況下,誤用了導致沒有分表策略的表使用了 shardingJdbc 來進行操作也是有可能的。

shardingJdbc3.1.0 在處理 sql 中含有 limit x,y 這種操作的時候會進行特殊處理。

類名: io.shardingsphere.core.routing.router.sharding.ParsingSQLRouter

格式化 SQL 和處理 limit 的操作

以下是截取的一段它的格式化 SQL 和處理 limit 的操作。

@Override
public SQLRouteResult route(final String logicSQL, final List<Object> parameters, final SQLStatement sqlStatement) {
    ......
    if (sqlStatement instanceof SelectStatement && null != ((SelectStatement) sqlStatement).getLimit()) {
        processLimit(parameters, (SelectStatement) sqlStatement);
    }
    ......
}
private void processLimit(final List<Object> parameters, final SelectStatement selectStatement) {
    boolean isNeedFetchAll = (!selectStatement.getGroupByItems().isEmpty() || !selectStatement.getAggregationSelectItems().isEmpty()) && !selectStatement.isSameGroupByAndOrderByItems();
    selectStatement.getLimit().processParameters(parameters, isNeedFetchAll, databaseType);
}

其中 selectStatement.getLimit () 得到的 Limit 類的實現(xiàn)有點問題,這個導致了問題就很大了。

類名: io.shardingsphere.core.parsing.parser.context.limit.Limit 

實現(xiàn)方法

以下是截取的一段它的實現(xiàn)方法

* @param parameters parameters
 * @param isFetchAll is fetch all data or not
 * @param databaseType database type
 */
public void processParameters(final List<Object> parameters, final boolean isFetchAll, final DatabaseType databaseType) {
    fill(parameters);
    rewrite(parameters, isFetchAll, databaseType);
}
private void fill(final List<Object> parameters) {
    int offset = 0;
    if (null != this.offset) {
        offset = -1 == this.offset.getIndex() ? getOffsetValue() : NumberUtil.roundHalfUp(parameters.get(this.offset.getIndex()));
        this.offset.setValue(offset);
    }
    int rowCount = 0;
    if (null != this.rowCount) {
        rowCount = -1 == this.rowCount.getIndex() ? getRowCountValue() : NumberUtil.roundHalfUp(parameters.get(this.rowCount.getIndex()));
        this.rowCount.setValue(rowCount);
    }
    if (offset < 0 || rowCount < 0) {
        throw new SQLParsingException("LIMIT offset and row count can not be a negative value.");
    }
}
private void rewrite(final List<Object> parameters, final boolean isFetchAll, final DatabaseType databaseType) {
    int rewriteOffset = 0;
    int rewriteRowCount;
    if (isFetchAll) {
        rewriteRowCount = Integer.MAX_VALUE;
    } else if (isNeedRewriteRowCount(databaseType)) {
        rewriteRowCount = null == rowCount ? -1 : getOffsetValue() + rowCount.getValue();
    } else {
        rewriteRowCount = rowCount.getValue();
    }
    if (null != offset && offset.getIndex() > -1) {
        parameters.set(offset.getIndex(), rewriteOffset);
    }
    if (null != rowCount && rowCount.getIndex() > -1) {
        parameters.set(rowCount.getIndex(), rewriteRowCount);
    }
}

在對 limit 語法進行處理的時候,會重寫掉這個 offset,使得 offset=0,這就導致了每次向后翻頁操作的數(shù)據(jù)會把前一次的分頁查詢結(jié)果也帶上,每向后翻一頁就會還是從 0 開始讀取數(shù)據(jù)。

所以,解決方案就是如果不是分表就不要去用 shardingJdbc,如果是分表就不要去分頁查詢,性能損耗太嚴重,畢竟它得聚合到內(nèi)存之后再進行分頁處理,這個數(shù)據(jù)量過大的時候真的很容易出事。

如果一定要這么玩,那么看下 shardingJdbc 的新版本 4.x 是否修復了這個 BUG,聽說已經(jīng)修復了,沒去試過。

以上就是shardingJdbc3.x 版本的分頁問題解析的詳細內(nèi)容,更多關(guān)于shardingJdbc版本分頁的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Springboot自動掃描包路徑來龍去脈示例詳解

    Springboot自動掃描包路徑來龍去脈示例詳解

    這篇文章主要介紹了Springboot自動掃描包路徑來龍去脈示例詳解,本文通過示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Java實現(xiàn)登錄密碼強度校驗的項目實踐

    Java實現(xiàn)登錄密碼強度校驗的項目實踐

    本文主要介紹了Java實現(xiàn)登錄密碼強度校驗的項目實踐,包括使用正則表達式匹配校驗和密碼強度校驗工具類這兩種方法,具有一定的參考價值,感興趣的可以了解一下
    2024-01-01
  • IDEA報錯:Process terminated的問題及解決

    IDEA報錯:Process terminated的問題及解決

    這篇文章主要介紹了IDEA報錯:Process terminated的問題及解決方案,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • spring-boot中spring-boot-maven-plugin報紅錯誤及解決

    spring-boot中spring-boot-maven-plugin報紅錯誤及解決

    這篇文章主要介紹了spring-boot中spring-boot-maven-plugin報紅錯誤及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 詳解java并發(fā)之重入鎖-ReentrantLock

    詳解java并發(fā)之重入鎖-ReentrantLock

    這篇文章主要介紹了java并發(fā)之重入鎖-ReentrantLock,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2019-03-03
  • Java創(chuàng)建數(shù)組的幾種方式總結(jié)

    Java創(chuàng)建數(shù)組的幾種方式總結(jié)

    下面小編就為大家?guī)硪黄狫ava創(chuàng)建數(shù)組的幾種方式總結(jié)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-10-10
  • SpringBoot?Starter的工作原理解析

    SpringBoot?Starter的工作原理解析

    SpringBootStarter是SpringBoot項目中用于簡化配置的工具,通過自動配置和條件加載機制,它自動生成所需的組件和服務(wù),減少了開發(fā)時間和配置工作,本文介紹SpringBoot?Starter的工作原理,感興趣的朋友一起看看吧
    2025-02-02
  • Springboot2以代碼的方式統(tǒng)一配置Jackson教程

    Springboot2以代碼的方式統(tǒng)一配置Jackson教程

    這篇文章主要介紹了Springboot2以代碼的方式統(tǒng)一配置Jackson教程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Java11中基于嵌套關(guān)系的訪問控制優(yōu)化詳解

    Java11中基于嵌套關(guān)系的訪問控制優(yōu)化詳解

    Java(和其他語言)通過內(nèi)部類支持嵌套類,要使其正常工作,需要編譯器執(zhí)行一些技巧,下面這篇文章主要給大家介紹了關(guān)于Java11中基于嵌套關(guān)系的訪問控制優(yōu)化的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • SpringBoot中的Aop用法示例詳解

    SpringBoot中的Aop用法示例詳解

    這篇文章主要介紹了SpringBoot中的Aop用法,本文結(jié)合示例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12

最新評論