1 IndexedDB 浏览器存储限制和清理标准

1. 全局限制(浏览器总共能存多少)

  • 浏览器能存的最大空间,是你电脑硬盘可用空间的 50%(比如 500G 硬盘可用,浏览器最多存 250G)。
  • 这是 “软限制”:存满了会自动删一些网站的数据(整个网站全删,避免数据乱),腾出空间。

2. 组限制(单个网站 / 域名组能存多少)

  • 每个 “主域名”(比如mozilla.orgfirefox.com)算一个 “组”,组内的子域名(比如www.mozilla.org)共享空间。
  • 每个组最多能存全局限制的 20%(比如全局是 250G,每个组最多存 50G),但最少不低于 10MB、最多不超过 2GB。
  • 这是 “硬限制”:组存满了不会自动删数据,直接存不进去了。

举个例子

如果你的硬盘可用 500G,浏览器全局最多存 250G:

  • mozilla.orgwww.mozilla.org这些子域名,加起来最多能存 50G(250G 的 20%);
  • firefox.com单独最多也能存 50G;
  • 要是浏览器存到 250G 了,会自动删一些网站的全部数据,直到空间够。

2 浏览器存储配额与驱逐标准(基于 MDN 文档)

一、浏览器如何区分不同网站的数据?

浏览器会将不同网站的数据存储在名为 “存储桶”(buckets)的独立位置,以此降低用户跨网站被追踪的风险,核心遵循“按源(Origin)管理” 原则:

  • “源” 的定义:由协议(如 HTTPS)、主机名(如example.com)和端口号共同决定。例如,https://example.comhttps://example.com/app/index.html属于同一源(协议、主机名、默认端口均相同);而http://example.com(协议不同)、https://blog.example.com(主机名不同)、https://example.com:8080(端口不同)均属于不同源。
  • 配额与驱逐规则的适用范围:本文所述的存储限制和数据驱逐逻辑,对整个 “源” 生效。即便一个源下运行多个子站点(如https://example.com/site1/https://example.com/site2/),也共享同一套规则。
  • 特殊情况:分区存储:部分场景下(如某源通过<iframe>嵌入到多个第三方源中),浏览器可能会将该源的数据进一步分区存储,但为简化说明,本文默认数据 “按源存储”。

二、哪些技术可在浏览器中存储数据?

Web 开发者可通过以下 5 类核心技术在浏览器本地存储数据,各类技术的功能定位不同,具体如下表所示:

技术(Technology) 描述(Description)
Cookies 小型文本数据,由服务器与浏览器双向传递,用于记录跨页面导航的状态信息(如登录会话标识)。
Web Storage 仅存储字符串类型的键值对,包含localStorage(持久存储)和sessionStorage(会话级存储)两种形式,适合存储简单的客户端状态。
IndexedDB 用于在浏览器中存储大型数据结构(如复杂 JSON 对象),支持索引功能,可实现高性能的数据查询,适合存储离线应用数据、大量用户生成内容等。
Cache API 持久化存储 HTTP 请求与响应的配对数据,核心作用是缓存静态资源(如 JS、CSS、图片),加速网页二次加载。
源私有文件系统(OPFS) 为当前源提供专属的文件系统,支持目录和文件的读写操作,适合需要按文件形式管理数据的场景(如编辑器的本地文件存储)。

此外,浏览器还会为源存储其他类型数据(如 WebAssembly 代码缓存),但上述 5 类是开发者可主动调用的核心存储技术。

三、浏览器存储的数据会持久存在吗?

一个源的数据在浏览器中分为“尽力而为存储(Best-effort)”和“持久存储(Persistent)”两种形式,持久性差异如下:

1. 尽力而为存储(默认形式)

  • 持久性规则:数据仅在 “源未超出配额、设备有足够存储空间、用户未手动删除” 的前提下保留。若浏览器需释放空间,可能会主动删除这类数据。
  • 用户感知:使用 IndexedDB、Cache API 等技术时,数据会自动以该形式存储,无需用户授权;浏览器删除数据时也不会打扰用户。
  • 实际留存概率:Chrome 团队研究表明,此类数据被浏览器删除的概率极低 —— 若用户定期访问某网站,即便数据是 “尽力而为” 形式,也几乎不会被驱逐。

2. 持久存储(需主动开启)

  • 持久性规则:仅当用户通过浏览器设置手动删除时,数据才会被清除,浏览器不会因空间不足主动驱逐。
  • 开启方式:开发者需调用navigator.storage.persist()方法申请,不同浏览器的授权逻辑不同:
    • Firefox:会弹出 UI 弹窗,征求用户同意;
    • Safari、Chrome/Edge 等 Chromium 系浏览器:根据用户与网站的交互历史(如访问频率、是否添加书签)自动同意或拒绝,不显示弹窗。

特殊场景:隐私浏览模式

在隐私浏览模式(如 Chrome 的 “无痕模式”、Edge 的 “InPrivate 模式”)下,浏览器可能会施加特殊配额,且所有存储数据会在模式关闭后被彻底删除。

四、浏览器最多能存储多少数据?

不同存储技术的配额差异极大,核心分为 “Cookies”“Web Storage”“其他技术(IndexedDB/OPFS 等)” 三类,具体限制如下:

1. Cookies

  • 不推荐用于数据存储:Cookies 会随每一次 HTTP 请求自动发送到服务器,若存储大量数据会增加请求体积、拖慢加载速度,仅适合传递少量状态信息(如会话 ID)。
  • 配额说明:因不推荐作为存储工具,MDN 未详细列出各浏览器的 Cookies 限制(通常单个 Cookie 约 4KB,同一源下最多存储 20-50 个)。

2. Web Storage(localStorage + sessionStorage

  • 统一配额:所有浏览器均限制 “同一源下,localStoragesessionStorage各最多存储 5MB”,合计 10MB。
  • 超出处理:若存储时超出配额,浏览器会抛出QuotaExceededError异常,需开发者通过try...catch代码块捕获处理。

3. 其他技术(IndexedDB、Cache API、OPFS 等)

这类技术的配额由浏览器独立管理,不同浏览器的计算逻辑差异较大,具体如下:

浏览器(Browser) 配额规则(按源计算) 示例(以 500GiB 硬盘为例)
Firefox 尽力而为模式:取 “用户配置文件所在磁盘总容量的 10%”“10GiB(同一 eTLD+1 域名组的上限)” 中的较小值;持久模式:最多为磁盘总容量的 50%(上限 8TiB),不受 eTLD+1 组限制。 尽力而为模式:最多存 10GiB(10GiB<500GiB×10%=50GiB);持久模式:最多存 250GiB(500GiB×50%)。
Chrome/Edge(Chromium 系) 尽力而为 / 持久模式统一配额:最多为磁盘总容量的 60%。 无论哪种模式,最多存 300GiB(500GiB×60%)。

Safari

(WebKit 内核)

分 “浏览器应用” 和 “嵌入式 WebView 应用” 两类:

1. 浏览器应用(如 Safari、可设为默认浏览器的第三方 WebKit 浏览器):同一源最多存磁盘总容量的 60%;

2. 嵌入式 WebView 应用(如 App 中的网页模块):同一源最多存 15%,但 “添加到桌面 / 程序坞的网站” 按浏览器应用配额(60%)计算;

3. 跨域框架:配额为父框架的 1/10;

4. 全局限制:所有源的总存储量,浏览器应用不超过磁盘的 80%,WebView 应用不超过 20%。

浏览器应用中:最多存 300GiB(500GiB×60%);WebView 应用中:最多存 75GiB(500GiB×15%)。

重要说明:配额计算的 “安全考量”

所有浏览器均基于 “磁盘总容量” 而非 “可用空间” 计算配额,目的是避免开发者通过 “检测可用空间变化” 追踪用户设备(即防止 “指纹识别”)。这意味着:即便源未超出配额,若设备实际可用空间不足,仍可能无法存储数据。

五、如何查看可用存储空间?

开发者可调用navigator.storage.estimate()方法,获取当前源的 “预估已用空间” 和 “预估可用空间”。需注意:

  • 该方法返回的是估算值,非精确值;
  • 若数据包含来自其他源的资源(如跨域图片缓存),浏览器会主动 “填充” 数据大小,避免泄露真实存储情况,进一步防范指纹识别。

六、当一个源的存储超出配额时,会发生什么?

若使用 IndexedDB、Cache API、OPFS 等技术存储数据时超出源的配额,浏览器会直接抛出QuotaExceededError异常。

开发者应对建议

  1. try...catch包裹存储操作代码,捕获异常并提示用户(如 “本地空间不足,请清理浏览器缓存”);
  2. 存储新数据前,主动删除无用旧数据(如过期的缓存资源、用户已删除的内容),释放空间。

七、数据何时会被驱逐?

浏览器仅会驱逐 “尽力而为存储” 的数据,不会触碰 “持久存储” 的数据,触发驱逐的场景分为三类:

1. 设备存储压力(最常见)

当设备可用空间过低(即 “存储压力”),且浏览器可用空间不足以容纳所有源的 “尽力而为数据” 时,浏览器会按LRU(最近最少使用)策略驱逐数据:先删除 “最近最少访问” 的源的全部数据,若空间仍不足,继续删除 “第二少访问” 的源,直至压力缓解。

2. 浏览器全局存储超限

部分浏览器会设定 “自身可使用的最大磁盘空间”(如 Chrome 当前限制为磁盘总容量的 80%)。若所有源的存储总量超出该限制,即便单个源未超配额,浏览器仍会按 LRU 策略驱逐 “尽力而为数据”。

3. Safari 主动驱逐(独有场景)

当 Safari 开启 “跨站跟踪防护” 时,若一个源在 “最近 7 天的浏览器使用中,无用户交互(如点击、触摸)”,其通过脚本创建的数据(如 IndexedDB 记录)会被主动删除;但服务器设置的 Cookies 不受此影响。

八、数据被驱逐时的规则是什么?

浏览器驱逐数据时,会遵循 “全量删除” 原则:

  • 对某一源,会删除其所有 “尽力而为存储” 的数据(包括 IndexedDB、Cache API、OPFS 等所有技术存储的内容),不会只删部分数据 —— 避免因数据不完整导致应用逻辑异常(如仅删除缓存却保留索引,造成查询错误)。

3 IndexedDB vs localStorage

直接说结论:localStorage 是 “简单小数据” 的轻量存储,IndexedDB 是 “复杂 / 大量数据” 的高性能存储,两者定位完全不同。

一、核心定位

  • localStorage是浏览器提供的键值对(Key-Value)轻量存储,仅支持字符串类型,适合存简单的客户端状态(如用户偏好、临时标识)。
  • IndexedDB是浏览器内置的NoSQL 数据库,支持复杂数据结构(对象、数组)、索引查询,适合存大量 / 结构化数据(如离线应用数据、用户本地内容)。

二、关键差异对比

维度 localStorage IndexedDB
数据类型

仅支持字符串

(需手动 JSON 序列化 / 反序列化)

支持任意 JS 类型(对象、数组、Blob 等)
存储容量 同一源下约 5MB(所有浏览器统一限制) 通常为浏览器全局配额的 20%(如硬盘 500G 则约 50G)
操作方式 同步操作(会阻塞主线程) 异步操作(不阻塞页面渲染)
查询能力 仅支持 “按键读取”,无查询 / 筛选功能 支持索引、游标,可按条件筛选 / 排序
事务支持 无事务,操作失败可能导致数据不一致 支持事务(原子性:要么全成功,要么全回滚)
适用场景 简单小数据(如用户主题、登录状态) 大量 / 复杂数据(如离线文章、本地表格)

三、使用示例

1. localStorage(简单场景)

// 存数据(需手动转字符串)
localStorage.setItem('userTheme', JSON.stringify({mode: 'dark', size: 16}));
// 取数据(需手动转对象)
const theme = JSON.parse(localStorage.getItem('userTheme'));
// 删除数据
localStorage.removeItem('userTheme');

2. IndexedDB(复杂场景)

// 打开数据库
const request = indexedDB.open('MyDB', 1);
request.onupgradeneeded = (e) => {
  const db = e.target.result;
  // 创建存储对象(类似表)+ 索引
  const store = db.createObjectStore('articles', {keyPath: 'id'});
  store.createIndex('byCategory', 'category'); // 按分类建立索引
};
request.onsuccess = (e) => {
  const db = e.target.result;
  // 事务:添加数据
  const tx = db.transaction('articles', 'readwrite');
  const store = tx.objectStore('articles');
  store.add({id: 1, title: 'Hello', category: 'note'});
  // 事务:按索引查询
  const index = store.index('byCategory');
  index.getAll('note').onsuccess = (e) => {
    console.log('分类为note的文章:', e.target.result);
  };
};

四、优缺点总结

  • localStorage 的优 / 缺点

  • ✅ 优点:API 简单、上手快;同步操作适合简单逻辑。

  • ❌ 缺点:容量小、阻塞主线程、无查询能力。

  • IndexedDB 的优 / 缺点

  • ✅ 优点:容量大、异步非阻塞、支持复杂查询 / 事务。

  • ❌ 缺点:API 复杂、学习成本高;不适合小数据场景。

事务(Transaction)

事务(Transaction) 是数据库中 “原子性的一组数据操作集合”,是与数据库交互的核心方式 —— 简单说,所有数据库的读 / 写操作都必须在事务中执行,核心目的是保证数据一致性和操作可靠性。

一、事务的核心特性

  • 原子性(核心):事务中的所有操作要么 “全部成功执行”,要么 “全部失败回滚”,不会出现 “部分成功” 的中间状态。比如向数据库添加 3 条数据,若第 2 条失败,前 1 条也会被撤销,数据库回到初始状态。
  • 范围固定:创建事务时会定义 “作用域”,即该事务能操作的数据库对象(如 IndexedDB 的 “对象存储 / Object Store”),且整个事务生命周期内作用域不能修改。
  • 短生命周期:事务设计为 “快速完成”,若执行时间过长,浏览器会主动终止它 —— 避免长期锁定存储资源,影响其他操作。
  • 可主动中止:开发者可手动调用接口中止事务,此时事务中已做的所有数据修改都会被回滚,数据库恢复到事务开始前的状态。

二、事务的关键规则(结合 IndexedDB 场景)

  1. 并发限制:一个数据库连接可同时存在多个活跃事务,但有约束:
    • 写事务(修改数据)的作用域不能重叠(比如不能同时有两个写事务操作同一个对象存储);
    • 读事务(仅查询数据)无重叠限制,可同时存在多个。
  2. 操作依赖:事务是所有数据操作的 “容器”—— 不管是读取数据、修改数据,还是创建 / 删除数据库对象(如 IndexedDB 的对象存储、索引),都必须在事务中进行,不能直接操作数据库。

三、IndexedDB 中的事务模式(3 种)

事务的模式决定了其能执行的操作权限,IndexedDB 中核心分为 3 类:

  • readonly(只读模式):仅能查询数据,不能修改(如读取对象存储中的记录),多个只读事务可同时操作同一作用域。
  • readwrite(读写模式):可查询、添加、修改、删除数据,同一作用域同一时间只能有一个读写事务。
  • versionchange(版本变更模式):唯一能创建 / 删除对象存储、索引的模式,用于数据库结构升级(如新增表、修改索引),执行时会锁定整个数据库,阻止其他事务并行。

四、事务的核心作用(为什么重要?)

对 IndexedDB 而言,事务是保证数据可靠性的关键:

  • 避免数据不一致:比如转账场景(A 账户减钱、B 账户加钱),若中途出错,事务回滚可防止 “只扣钱没加钱” 的 bug;
  • 控制资源竞争:通过锁定机制,防止多个操作同时修改同一数据(如两个写事务同时更新同一条记录);
  • 简化错误处理:无需单独处理每个操作的失败,只需判断事务整体成功 / 失败,统一回滚或提交。

简单总结:事务就像数据库操作的 “打包工具”,把一组相关操作绑在一起,要么全成、要么全退,同时通过规则控制并发和资源占用,是 IndexedDB 中最核心的概念之一。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐