最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SQLite三種分片策略的深度解析

 更新時(shí)間:2026年04月18日 08:53:23   作者:Newbe36524  
文章介紹了HagiCode項(xiàng)目中的三種不同場(chǎng)景下的SQLite分片方案,文章強(qiáng)調(diào)了選擇合適分片方案的重要性,并提供了詳細(xì)的實(shí)踐指南,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧

SQLite 分片方案實(shí)戰(zhàn):三種分片策略的深度對(duì)比

當(dāng)單文件 SQLite 遇到并發(fā)瓶頸,我們?cè)撊绾纹凭??本文分?HagiCode 項(xiàng)目中三種不同場(chǎng)景下的 SQLite 分片方案,幫你理解如何選擇合適的分片策略。

全民制作人們大家好,我是 HagiCode 制作人俞坤。

背景

在構(gòu)建高性能應(yīng)用時(shí),單文件 SQLite 數(shù)據(jù)庫(kù)會(huì)碰到很現(xiàn)實(shí)的問(wèn)題。用戶(hù)量和數(shù)據(jù)量一上來(lái),這些狀況就會(huì)排隊(duì)找上門(mén):

  • 寫(xiě)入操作開(kāi)始排隊(duì),響應(yīng)時(shí)間肉眼可見(jiàn)地變長(zhǎng)
  • 查詢(xún)性能隨數(shù)據(jù)增長(zhǎng)往下掉
  • 多線程訪問(wèn)時(shí)頻繁出現(xiàn) "database is locked" 錯(cuò)誤

很多人第一反應(yīng)是:要不要直接遷移到 PostgreSQL 或者 MySQL?這波操作雖然能解決問(wèn)題,但部署復(fù)雜度會(huì)直線上升。有沒(méi)有更輕量的方案?

答案是:分片。說(shuō)到底,工程問(wèn)題還是要回到工程方法里解決,通過(guò)將數(shù)據(jù)分散到多個(gè) SQLite 文件,可以顯著提升并發(fā)能力和查詢(xún)性能,同時(shí)保持 SQLite 的輕量級(jí)特性。

關(guān)于 HagiCode

本文分享的方案來(lái)自我們?cè)?HagiCode 項(xiàng)目中的實(shí)踐經(jīng)驗(yàn)。作為一個(gè) AI 代碼助手項(xiàng)目,HagiCode 需要處理大量的對(duì)話消息、狀態(tài)持久化和事件歷史記錄。正是在解決這些實(shí)際問(wèn)題的過(guò)程中,我們總結(jié)出了三種不同場(chǎng)景下的分片方案。

工欲善其事,必先利其器,但這些"器"怎么用,還得看具體的"事"是什么。

我們的代碼倉(cāng)庫(kù)在 github.com/HagiCode-org/site,歡迎感興趣的朋友深入了解。

三種分片方案概覽

經(jīng)過(guò)對(duì) HagiCode 代碼庫(kù)的分析,我們發(fā)現(xiàn)了三種針對(duì)不同業(yè)務(wù)場(chǎng)景的 SQLite 分片方案:

  1. Session Message 分片存儲(chǔ):AI 對(duì)話消息存儲(chǔ),特點(diǎn)是高頻寫(xiě)入、基于 Session 的隔離查詢(xún)
  2. Orleans Grain 分片存儲(chǔ):分布式框架狀態(tài)持久化,特點(diǎn)是跨節(jié)點(diǎn)訪問(wèn)、需要確定性路由
  3. Hero History 分片存儲(chǔ):游戲化系統(tǒng)歷史事件記錄,特點(diǎn)是事件溯源、需要遷移兼容

雖然業(yè)務(wù)場(chǎng)景不同,但三者都遵循相同的核心設(shè)計(jì)原則:

  • 確定性路由:直接從業(yè)務(wù) ID 計(jì)算分片,無(wú)需元數(shù)據(jù)表
  • 透明訪問(wèn):上層通過(guò)統(tǒng)一接口操作,不感知分片存在
  • 獨(dú)立存儲(chǔ):每個(gè)分片是完全獨(dú)立的 SQLite 文件
  • 并發(fā)優(yōu)化:WAL 模式 + busy_timeout 降低鎖競(jìng)爭(zhēng)

很多人會(huì)問(wèn):為什么不搞一套通用的分片方案?這個(gè)問(wèn)題問(wèn)得很實(shí)在,我們直接上結(jié)論:工程上沒(méi)有萬(wàn)能方案,只有最貼合當(dāng)前業(yè)務(wù)場(chǎng)景的方案。接下來(lái)我們深入對(duì)比這三種方案的具體實(shí)現(xiàn)。

分片策略對(duì)比

分片數(shù)量與命名規(guī)則

方面Session MessageOrleans GrainHero History
分片數(shù)量256 (16²)10010
命名規(guī)則16 進(jìn)制 (00-ff)10 進(jìn)制 (00-99)10 進(jìn)制 (0-9)
存儲(chǔ)目錄DataDir/messages/DataDir/orleans/grains/DataDir/hero-history/
文件名模式{shard}.dbgrains-{shard}.db{shard}.db

為什么分片數(shù)量差異這么大?這取決于業(yè)務(wù)特點(diǎn)。換句話說(shuō),模型會(huì)說(shuō),工具會(huì)變,工作流會(huì)升級(jí),但工程上的基本盤(pán)一直都在那里:你得先搞清楚自己要解決什么問(wèn)題。

  • Session Message 使用 256 個(gè)分片,因?yàn)閷?duì)話消息的寫(xiě)入頻率最高,需要更多的分片來(lái)分散負(fù)載
  • Orleans Grain 使用 100 個(gè)分片,平衡了并發(fā)性能和管理復(fù)雜度
  • Hero History 只用 10 個(gè)分片,因?yàn)闅v史事件寫(xiě)入頻率較低,且需要考慮遷移成本

路由算法差異

路由算法是分片方案的核心,決定了數(shù)據(jù)如何分布到各個(gè)分片。三種方案使用了不同的路由策略:

// Session Message: GUID 后兩位 16 進(jìn)制
var normalized = Guid.Parse(sessionId.Value).ToString("N").ToLowerInvariant();
return normalized[^2..];  // 取末兩位 16 進(jìn)制字符
// Orleans Grain: 提取數(shù)字后兩位取模
var digits = ExtractDigits(grainId);  // 提取所有數(shù)字
var lastTwoDigits = (digits[^2] * 10) + digits[^1];
return lastTwoDigits % shardCount;
// Hero History: 末位字符 ASCII 值取模
return heroId[^1] % 10;

設(shè)計(jì)思路解析

  • Session Message 的 ID 是 GUID,轉(zhuǎn)換為 16 進(jìn)制后取末兩位,可以得到均勻分布的 256 個(gè)分片
  • Orleans Grain 的 ID 格式不統(tǒng)一,可能包含字母和數(shù)字,所以提取所有數(shù)字后取模
  • Hero History 的 ID 是字符串,直接用末位字符的 ASCII 值取模,簡(jiǎn)單但分布可能不夠均勻

關(guān)鍵點(diǎn):無(wú)論使用哪種算法,都必須保證同一 ID 永遠(yuǎn)映射到同一分片。這是分布式系統(tǒng)中最基本的要求,否則會(huì)導(dǎo)致數(shù)據(jù)不一致。說(shuō)到底,路由不穩(wěn)定,一切努力都是零。

初始化策略差異

方面Session MessageOrleans GrainHero History
初始化時(shí)機(jī)按需懶加載啟動(dòng)時(shí)全量并行初始化按需懶加載
并發(fā)控制Lazy 防重復(fù)初始化Parallel.ForEachAsyncLazy 防重復(fù)初始化

為什么 Orleans Grain 選擇啟動(dòng)時(shí)全量初始化?

因?yàn)?Orleans 是分布式框架,Grain 可能被調(diào)度到任意節(jié)點(diǎn)。如果在運(yùn)行時(shí)才發(fā)現(xiàn)分片文件不存在,會(huì)導(dǎo)致請(qǐng)求失敗。啟動(dòng)時(shí)全量初始化雖然會(huì)延長(zhǎng)啟動(dòng)時(shí)間,但能確保運(yùn)行時(shí)的穩(wěn)定性。能跑起來(lái)只是開(kāi)始,能維護(hù)下去才算本事。

懶加載的優(yōu)勢(shì)

對(duì)于 Session Message 和 Hero History,使用懶加載可以減少啟動(dòng)時(shí)間,只有在真正需要訪問(wèn)某個(gè)分片時(shí)才創(chuàng)建文件和初始化 Schema。使用 Lazy<Task> 可以防止并發(fā)初始化時(shí)的競(jìng)態(tài)條件。這個(gè)設(shè)計(jì)看著簡(jiǎn)單,但在真實(shí)項(xiàng)目里能省掉很多不必要的麻煩。

Schema 設(shè)計(jì)特點(diǎn)

三種方案的 Schema 設(shè)計(jì)反映了各自的業(yè)務(wù)特點(diǎn):

Session Message

  • 支持 Event Sourcing 模式(事件表 + 快照表)
  • 包含消息內(nèi)容塊子表(MessageContentBlocks)
  • 具有壓縮和壓縮標(biāo)記字段,支持后續(xù)優(yōu)化

Orleans Grain

  • 最簡(jiǎn)設(shè)計(jì):?jiǎn)伪?GrainState
  • JSON 序列化存儲(chǔ)狀態(tài)
  • ETag 樂(lè)觀并發(fā)控制

Hero History

  • 時(shí)間線查詢(xún)優(yōu)化索引
  • DedupeKey 唯一約束防重復(fù)
  • 支持多種事件類(lèi)型和狀態(tài)

從這些設(shè)計(jì)中可以看出,Schema 設(shè)計(jì)應(yīng)該緊密貼合業(yè)務(wù)需求,而不是追求通用性。Orleans Grain 的簡(jiǎn)單設(shè)計(jì)正是因?yàn)樗恍枰鎯?chǔ)序列化后的狀態(tài),不需要復(fù)雜的查詢(xún)能力。這波不是玄學(xué),是工程。別急著把名字起得太大,先看看這東西能不能在團(tuán)隊(duì)里活過(guò)兩個(gè)迭代。

并發(fā)配置對(duì)比

三種方案都使用了相同的 SQLite 并發(fā)優(yōu)化配置:

PRAGMA journal_mode=WAL;      -- 寫(xiě)前日志模式
PRAGMA synchronous=NORMAL;     -- 降低持久化開(kāi)銷(xiāo)
PRAGMA busy_timeout=5000;      -- 5秒忙等待
PRAGMA foreign_keys=ON;        -- 外鍵約束

WAL 模式的優(yōu)勢(shì)

傳統(tǒng)的回滾日志模式在寫(xiě)入時(shí)會(huì)產(chǎn)生鎖競(jìng)爭(zhēng),而 WAL 模式允許讀寫(xiě)并發(fā)進(jìn)行。這在大數(shù)據(jù)量場(chǎng)景下可以顯著提升性能。很多人不知道這個(gè)配置,其實(shí)它比你想的要重要得多。

synchronous=NORMAL 的權(quán)衡

設(shè)置為 FULL 可以保證最高安全性,但會(huì)顯著降低性能。NORMAL 模式在安全性和性能之間取得了平衡,對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō)是合適的選擇。這個(gè)配置不需要糾結(jié)太久,NORMAL 就夠了。

如何選擇分片策略

基于對(duì) HagiCode 三種方案的分析,我們可以總結(jié)出以下決策矩陣:

高吞吐量場(chǎng)景 → 更多分片(如 Message 用 256)
簡(jiǎn)單維護(hù)性   → 較少分片(如 Hero History 用 10)
數(shù)字 ID 為主 → 取模算法(Orleans Grain)
GUID 為主    → 16 進(jìn)制后綴(Session Message)
字符串 ID    → ASCII 取模(Hero History)

分片數(shù)量選擇的經(jīng)驗(yàn)值

  • 太少(< 10):并發(fā)提升有限,分片意義不大
  • 太多(> 1000):文件管理復(fù)雜,連接池開(kāi)銷(xiāo)大
  • 經(jīng)驗(yàn)值:10-100 個(gè)分片適用于大多數(shù)場(chǎng)景
  • 極高并發(fā)場(chǎng)景:可以考慮 256 個(gè)分片

這事你要是只看演示,確實(shí)容易上頭;可一旦進(jìn)了生產(chǎn)環(huán)境,賬就得一筆一筆算清楚。很多問(wèn)題不是不能做,只是沒(méi)把代價(jià)算明白。

實(shí)踐指南

實(shí)現(xiàn)標(biāo)準(zhǔn)化分片路由器

public interface IShardResolver<TId>
{
    string ResolveShardKey(TId id);
}
// 16 進(jìn)制分片(適用于 GUID)
public class HexSuffixShardResolver : IShardResolver<string>
{
    private readonly int _suffixLength;
    public HexSuffixShardResolver(int suffixLength = 2)
    {
        _suffixLength = suffixLength;
    }
    public string ResolveShardKey(string id)
    {
        var normalized = id.Replace("-", "").ToLowerInvariant();
        return normalized[^_suffixLength..];
    }
}
// 數(shù)字取模分片(適用于純數(shù)字 ID)
public class NumericModuloShardResolver : IShardResolver<long>
{
    private readonly int _shardCount;
    public NumericModuloShardResolver(int shardCount)
    {
        _shardCount = shardCount;
    }
    public string ResolveShardKey(long id)
    {
        return (id % _shardCount).ToString("D2");
    }
}

統(tǒng)一連接工廠模式

public class ShardedConnectionFactory<TOptions>
{
    private readonly ConcurrentDictionary<string, Lazy<Task>> _initializationTasks = new();
    private readonly TOptions _options;
    private readonly IShardSchemaInitializer _initializer;
    public ShardedConnectionFactory(
        TOptions options,
        IShardSchemaInitializer initializer)
    {
        _options = options;
        _initializer = initializer;
    }
    public async Task<TDbContext> CreateAsync(string shardKey, CancellationToken ct)
    {
        var connectionString = BuildConnectionString(shardKey);
        // 使用 Lazy<Task> 防止并發(fā)初始化
        var initTask = _initializationTasks.GetOrAdd(
            connectionString,
            _ => new Lazy<Task>(() => InitializeShardAsync(connectionString, ct))
        );
        await initTask.Value;
        return CreateDbContext(connectionString);
    }
    private async Task InitializeShardAsync(string connectionString, CancellationToken ct)
    {
        await _initializer.InitializeAsync(connectionString, ct);
    }
    private string BuildConnectionString(string shardKey)
    {
        var shardPath = Path.Combine(_options.BaseDirectory, $"{shardKey}.db");
        return $"Data Source={shardPath}";
    }
    private TDbContext CreateDbContext(string connectionString)
    {
        // 根據(jù)具體的 ORM 創(chuàng)建 DbContext
        return Activator.CreateInstance(typeof(TDbContext), connectionString) as TDbContext;
    }
}

Schema 初始化最佳實(shí)踐

public class SqliteShardInitializer : IShardSchemaInitializer
{
    public async Task InitializeAsync(string connectionString, CancellationToken ct)
    {
        await using var connection = new SqliteConnection(connectionString);
        await connection.OpenAsync(ct);
        // 并發(fā)優(yōu)化配置
        await connection.ExecuteAsync("""
            PRAGMA journal_mode=WAL;
            PRAGMA synchronous=NORMAL;
            PRAGMA busy_timeout=5000;
            PRAGMA foreign_keys=ON;
        """);
        // 創(chuàng)建表結(jié)構(gòu)
        await connection.ExecuteAsync("""
            CREATE TABLE IF NOT EXISTS Entities (
                Id TEXT PRIMARY KEY,
                CreatedAt TEXT NOT NULL,
                UpdatedAt TEXT NOT NULL,
                Data TEXT NOT NULL,
                ETag TEXT
            );
        """);
        // 創(chuàng)建索引
        await connection.ExecuteAsync("""
            CREATE INDEX IF NOT EXISTS IX_Entities_CreatedAt
            ON Entities(CreatedAt DESC);
            CREATE INDEX IF NOT EXISTS IX_Entities_UpdatedAt
            ON Entities(UpdatedAt DESC);
        """);
    }
}

關(guān)鍵注意事項(xiàng)

1. 路由穩(wěn)定性

路由算法必須保證同一 ID 永遠(yuǎn)映射到同一分片。避免使用隨機(jī)或時(shí)間相關(guān)的計(jì)算,也不要在算法中引入可變參數(shù)。

2. 分片數(shù)量選擇

分片數(shù)量應(yīng)該在設(shè)計(jì)階段確定,后期修改非常困難。需要考慮:

  • 當(dāng)前和未來(lái)的并發(fā)量
  • 單個(gè)分片的管理成本
  • 數(shù)據(jù)遷移的復(fù)雜度

3. 遷移考慮

Hero History 方案展示了完整的遷移路徑:

  1. 新建分片存儲(chǔ)基礎(chǔ)設(shè)施
  2. 實(shí)現(xiàn)遷移服務(wù)將主庫(kù)數(shù)據(jù)復(fù)制到分片
  3. 驗(yàn)證遷移后查詢(xún)兼容性
  4. 切換讀寫(xiě)路徑到分片
  5. 清理主庫(kù)舊表

設(shè)計(jì)分片方案時(shí)就需要考慮未來(lái)的遷移需求。Talk is cheap. Show me the code,但光有代碼還不夠,你還得有完整的遷移路徑。一次成功不叫體系,持續(xù)成功才叫體系。

4. 監(jiān)控與運(yùn)維

  • 監(jiān)控各分片的大小分布,及時(shí)發(fā)現(xiàn)數(shù)據(jù)傾斜
  • 設(shè)置告警檢測(cè)分片熱點(diǎn),避免單個(gè)分片成為瓶頸
  • 定期檢查 WAL 文件大小,防止磁盤(pán)空間占用過(guò)多
  • 建立分片健康檢查機(jī)制

5. 測(cè)試覆蓋

  • 測(cè)試邊界條件(空 ID、特殊字符、超長(zhǎng) ID)
  • 驗(yàn)證路由確定性,確保同一 ID 總是映射到同一分片
  • 并發(fā)寫(xiě)入壓力測(cè)試,驗(yàn)證鎖競(jìng)爭(zhēng)得到有效緩解
  • 遷移測(cè)試,確保數(shù)據(jù)完整性和一致性

總結(jié)

通過(guò)對(duì)比 HagiCode 項(xiàng)目中的三種 SQLite 分片方案,我們可以看到:

  1. 沒(méi)有萬(wàn)能的解決方案:不同業(yè)務(wù)場(chǎng)景需要不同的分片策略
  2. 核心原則是通用的:確定性路由、透明訪問(wèn)、獨(dú)立存儲(chǔ)、并發(fā)優(yōu)化
  3. 設(shè)計(jì)要面向未來(lái):考慮遷移路徑和運(yùn)維成本

如果你的項(xiàng)目正在使用 SQLite,并且開(kāi)始遇到并發(fā)瓶頸,希望這篇文章能為你提供一些思路。不需要急著遷移到重量級(jí)數(shù)據(jù)庫(kù),有時(shí)候合適的分片方案就能解決問(wèn)題。

當(dāng)然,分片不是銀彈。在選擇分片方案之前,先確保:

  • 你已經(jīng)優(yōu)化了單表查詢(xún)性能
  • 你已經(jīng)使用了合適的索引
  • 你已經(jīng)啟用了 WAL 模式

只有在這些優(yōu)化都做完之后,仍然存在性能瓶頸時(shí),才考慮引入分片。你能把簡(jiǎn)單的事情做好,這本身就是一種能力。

很多話講一遍不如做一遍,接下來(lái)就讓工程結(jié)果自己發(fā)聲。

參考資料

到此這篇關(guān)于SQLite三種分片策略的深度解析的文章就介紹到這了,更多相關(guān)SQLite 分片策略?xún)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解hive常見(jiàn)表結(jié)構(gòu)

    詳解hive常見(jiàn)表結(jié)構(gòu)

    hive是基于Hadoop的一個(gè)數(shù)據(jù)倉(cāng)庫(kù)工具,用來(lái)進(jìn)行數(shù)據(jù)提取、轉(zhuǎn)化、加載,這是一種可以存儲(chǔ)、查詢(xún)和分析存儲(chǔ)在Hadoop中的大規(guī)模數(shù)據(jù)的機(jī)制,這篇文章主要介紹了hive常見(jiàn)表結(jié)構(gòu),需要的朋友可以參考下
    2022-08-08
  • 數(shù)據(jù)庫(kù)的ACID特性術(shù)語(yǔ)詳解

    數(shù)據(jù)庫(kù)的ACID特性術(shù)語(yǔ)詳解

    這篇文章主要介紹了數(shù)據(jù)庫(kù)的ACID特性術(shù)語(yǔ)詳解,ACID就是:原子性(Atomicity )、一致性( Consistency )、隔離性( Isolation)和持久性(Durabilily),本文分別解釋了它們,需要的朋友可以參考下
    2015-02-02
  • 寫(xiě)出高性能SQL語(yǔ)句的35條方法分析

    寫(xiě)出高性能SQL語(yǔ)句的35條方法分析

    高性能的SQL語(yǔ)句能提高頁(yè)面的執(zhí)行效率,讓你的服務(wù)器運(yùn)行的更為流暢,所以大家在以后的使用過(guò)程中,盡量的考慮到效率。
    2009-10-10
  • dataGrip顯示clickhouse時(shí)間字段不正確的問(wèn)題

    dataGrip顯示clickhouse時(shí)間字段不正確的問(wèn)題

    最近做數(shù)據(jù)遷移碰到一個(gè)問(wèn)題,源數(shù)據(jù)和目的端數(shù)據(jù),導(dǎo)入的時(shí)間怎么都差8個(gè)小時(shí),本文就來(lái)介紹一下如何解決,感興趣的可以了解一下
    2021-09-09
  • SQL注入詳解及防范方法

    SQL注入詳解及防范方法

    本文詳細(xì)講解了SQL注入及防范方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • SAP技巧之修改自帶搜索幫助為自定數(shù)據(jù)集

    SAP技巧之修改自帶搜索幫助為自定數(shù)據(jù)集

    這篇文章主要為大家介紹了SAP技巧之修改自帶搜索幫助為自定數(shù)據(jù)集實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • RBAC簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    RBAC簡(jiǎn)介_(kāi)動(dòng)力節(jié)點(diǎn)Java學(xué)院整理

    這篇文章主要介紹了RBAC簡(jiǎn)介,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • Navicat premium連接數(shù)據(jù)庫(kù)出現(xiàn):2003 Can''t connect to MySQL server on''localhost''(10061)

    Navicat premium連接數(shù)據(jù)庫(kù)出現(xiàn):2003 Can''t connect to MySQL server o

    這篇文章主要介紹了Navicat premium連接數(shù)據(jù)庫(kù)出現(xiàn):2003 - Can't connect to MySQL server on 'localhost' (10061 "Unknown error")的問(wèn)題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-11-11
  • Windows10用Navicat?定時(shí)備份報(bào)錯(cuò)80070057的問(wèn)題解析

    Windows10用Navicat?定時(shí)備份報(bào)錯(cuò)80070057的問(wèn)題解析

    這篇文章主要介紹了Windows10用Navicat?定時(shí)備份報(bào)錯(cuò)80070057的問(wèn)題,本文通過(guò)圖文并茂的形式給大家分享問(wèn)題所在原因及解決方案,需要的朋友可以參考下
    2023-10-10
  • sql注入之必備的基礎(chǔ)知識(shí)

    sql注入之必備的基礎(chǔ)知識(shí)

    這篇文章所有的知識(shí)點(diǎn)都是在sql注入中最常用到也是最基礎(chǔ)的知識(shí)點(diǎn)。對(duì)于一個(gè)需要精通sql語(yǔ)句的web安全工程師來(lái)說(shuō),下面的知識(shí)是必須要掌握的。下面的知識(shí)也是學(xué)習(xí)sql注入最基本的知識(shí)。下面大家來(lái)一起看看吧。
    2016-09-09

最新評(píng)論

木兰县| 珲春市| 潼关县| 怀安县| 和静县| 新巴尔虎右旗| 观塘区| 长沙市| 筠连县| 女性| 双流县| 海南省| 庆云县| 宣城市| 叶城县| 西乡县| 且末县| 桃源县| 双桥区| 崇仁县| 长武县| 墨玉县| 竹山县| 翁牛特旗| 永和县| 兴仁县| 庆云县| 维西| 平南县| 介休市| 茶陵县| 阿克苏市| 西昌市| 文成县| 海安县| 古浪县| 阿巴嘎旗| 西林县| 鹤庆县| 宝清县| 沾化县|