当前位置: 首页 > news >正文

03-事务高频面试总结

目录

1. 解释事务的 ACID 特性,并说明 SQLite 是如何保证每一项的。

2. 什么是自动提交模式?为什么在批量写入时要显式使用 BEGIN...COMMIT?

3. 解释 BEGIN DEFERRED、BEGIN IMMEDIATE、BEGIN EXCLUSIVE 的区别和使用场景。

4. SQLite 的锁机制是怎样的?为什么说它适合“多读少写”的场景?

5. 遇到 database is locked 错误时,有哪些解决办法?(设计 + 配置)

设计层面(架构/SQL 习惯)

配置 / 代码层面

6. 解释 SQLite 的隔离级别,它能否读未提交的数据?PRAGMA read_uncommitted 有什么作用?

7. 在高并发读多写少场景下,你会如何配置 SQLite 来提升并发能力?

8. 什么是 WAL 模式?它对读写并发和崩溃恢复有什么影响?

9. 多线程访问 SQLite 时,你如何管理连接和事务?


1. 解释事务的 ACID 特性,并说明 SQLite 是如何保证每一项的。

ACID:

  1. A 原子性(Atomicity)

    要么全成功,要么全失败。
    SQLite:

    • 用事务日志(rollback journal / WAL)记录修改

    • 出错或 ROLLBACK 时,用日志把数据恢复到事务开始前的状态

  2. C 一致性(Consistency)

    事务前后,数据库从一个合法状态到另一个合法状态(约束不被破坏)。
    SQLite:

    • 通过约束(PRIMARY KEY、UNIQUE、NOT NULL、CHECK、FOREIGN KEY)+ 事务

    • 约束失败 → 语句报错 → 事务可整体回滚,避免留下“半合法”状态

  3. I 隔离性(Isolation)

    并发事务互不干扰,看起来像串行执行。
    SQLite:

    • 使用文件锁和多版本读(特别是 WAL 模式)

    • 读事务看到的是一个一致快照,不会看到别的事务的中间状态(不读未提交)

  4. D 持久性(Durability)

    提交后的数据崩溃也不会丢。
    SQLite:

    • 提交时把日志 / WAL 同步写入磁盘(受 PRAGMA synchronous 控制)

    • 崩溃后启动时,根据日志/WAL 恢复到一致状态


2. 什么是自动提交模式?为什么在批量写入时要显式使用 BEGIN...COMMIT

自动提交模式(auto-commit):

只要你没有显式 BEGIN 事务,SQLite 会把每一条写语句当成一个独立事务

  • 语句开始前:隐式 BEGIN

  • 语句成功:隐式 COMMIT

  • 语句失败:隐式 ROLLBACK

批量写时为什么要显式 BEGIN...COMMIT

  • 不写 BEGIN
    每条 INSERT/UPDATE/DELETE 都是
    BEGIN → 执行 → COMMIT → 每条都刷一次磁盘,非常慢

  • 显式事务:

    BEGIN;INSERT ...;INSERT ...;INSERT ...;
    COMMIT;
    
    • 多条语句共享一个事务

    • 只在最后 COMMIT 时落盘一次

    • 大幅提升写入性能

    • 同时保证“这几条要么一起成功,要么一起失败”(原子性)


3. 解释 BEGIN DEFERREDBEGIN IMMEDIATEBEGIN EXCLUSIVE 的区别和使用场景。

三种模式都是“开始事务”,区别在于什么时候抢锁、锁多大

  1. BEGIN DEFERRED(默认)

    • 开始事务 不立即加写锁

    • 真正需要读/写时再申请相应锁

    • 优点:锁持有时间短,更灵活

    • **使用场景:**大多数普通事务

  2. BEGIN IMMEDIATE

    • 一开始就尝试获取写锁(RESERVED)

    • 阻止其他连接再开启写事务,但读仍可进行

    • 使用场景:你已经确定本事务会写,希望尽早占住写权限,避免做到一半才发现写不了

  3. BEGIN EXCLUSIVE

    • 一开始就尝试获取排他锁(EXCLUSIVE)

    • 阻止其他读写,几乎“独占数据库文件”

    • **使用场景:**大批量迁移、重建索引、一次性大改动,能接受这段时间其他访问都暂停


4. SQLite 的锁机制是怎样的?为什么说它适合“多读少写”的场景?

锁机制(非 WAL 模式下):

  • 锁是加在整个数据库文件上的(不是行锁)

  • 主要锁级别:

    • SHARED(共享锁):读事务用,多个读可以并发

    • RESERVED:写事务准备写时占位,只允许一个写者

    • PENDING:写事务准备升级为排他锁,阻止新读者进来

    • EXCLUSIVE(排他锁):写事务真正写回数据库时独占文件,挡住其他读写

读/写流程(简化):

  • 读:无锁 → SHARED → 释放

  • 写:无锁 → (可能 SHARED)→ RESERVED → PENDING → EXCLUSIVE → 释放

为什么适合“多读少写”?

因为:

  • 可以有很多并发读(多个 SHARED 锁)

  • 同一时刻只能有一个写者(写要升级到 EXCLUSIVE),

  • 写的时候会影响其他读写

所以:

  • 读多写少 → 冲突少,表现很好

  • 写多并发 → 写锁竞争严重,频繁 database is locked

(使用 WAL 后,读写并发会好很多,但“单写者”本质不变)


5. 遇到 database is locked 错误时,有哪些解决办法?(设计 + 配置)

可以从设计层面配置/代码层面两块回答:

设计层面(架构/SQL 习惯)

  1. 缩短事务时间

    • 事务里只做必要的 SQL

    • 不要在事务中做复杂计算 / 网络 IO

    • 尽快 COMMITROLLBACK,减少锁持有时间

  2. 避免长时间大查询(长读事务)

    • 使用分页查询 LIMIT/OFFSET

    • 避免一个 SELECT 持有读锁很久,阻塞写

  3. 控制写的粒度和频率

    • 批量写时用显式事务,减少事务次数

    • 尽量把高频写挪到队列/后台任务

  4. 读多写少时开启 WAL 模式

    • 减少写对读的影响(写不那么挡读)

配置 / 代码层面

  1. 设置 busy_timeout

    PRAGMA busy_timeout = 3000;  -- 最多等 3000ms 再报错
    
    • 避免刚好撞锁时立刻失败,给对方一点时间释放锁

  2. 应用层重试机制

    • 捕获 database is locked / busy 异常

    • sleep 一小会儿后重试几次

  3. 合理使用 WAL 模式

    • PRAGMA journal_mode = WAL;

    • 提升读写并发能力,减少锁冲突


6. 解释 SQLite 的隔离级别,它能否读未提交的数据?PRAGMA read_uncommitted 有什么作用?

隔离级别:

  • SQLite 官方默认隔离行为接近 SERIALIZABLE / snapshot isolation

    • 读事务看到的是一个一致的“快照”

    • 不会读到其他事务的未提交数据(不支持脏读)

能否读未提交的数据?

不能。
即使你设置了 PRAGMA read_uncommitted = 1,SQLite 实际上也不会真的让你看到未提交的数据,更多是为了兼容 SQL 标准接口。

PRAGMA read_uncommitted 的作用?

PRAGMA read_uncommitted = 1;
PRAGMA read_uncommitted;
  • 语义上是“允许脏读”

  • 但在 SQLite 的实现中:

    • 读未提交的数据并不是真的被允许

    • 官方文档说明它基本是无效/被忽略的开关

    • SQLite 仍然提供一致性快照,避免脏读

可以在面试中简单说:

SQLite 的隔离级别类似于快照隔离,默认不允许读未提交数据。
PRAGMA read_uncommitted 在 SQLite 中基本不会真的打开脏读,只是为了兼容 SQL 标准接口。


7. 在高并发读多写少场景下,你会如何配置 SQLite 来提升并发能力?

可以从配置 + 使用习惯两块回答:

  1. 启用 WAL 模式

    PRAGMA journal_mode = WAL;
    
    • 写入追加到 WAL 文件

    • 大部分场景下:写不阻塞读,读写并发能力大幅提升

  2. 适当设置 busy_timeout

    PRAGMA busy_timeout = 3000;  -- 例如 3 秒
    
    • 避免短暂锁冲突导致立刻报错

    • 给写事务一些时间完成并释放锁

  3. 合理设置 synchronous 策略(视场景而定)

    PRAGMA synchronous = NORMAL;  -- 读多写少、允许一点点风险
    -- 或 FULL(更安全,稍微慢一些)
    
  4. 优化查询与索引

    • 给频繁查询的条件列建索引,减少查询时间

    • 查询快 → 事务短 → 锁持有时间短

  5. 设计上保证“写少、短事务”

    • 批量写用显式事务

    • 避免长时间读事务


8. 什么是 WAL 模式?它对读写并发和崩溃恢复有什么影响?

WAL(Write-Ahead Logging)模式:

写前日志模式:写操作不直接改主库文件(xxx.db),
而是先把修改追加写xxx.db-wal 日志文件里,
后面再通过 checkpoint 把 WAL 内容合并回主库。

对读写并发的影响:

  • 写:写入 WAL 文件,主库暂时不动

  • 读:从主库 + WAL 合成一个当前视图
    → 大部分情况下:“有人在写,别人仍然可以读”

  • 结果:读写并发明显提升,尤其适合读多写少场景

对崩溃恢复的影响:

  • 崩溃时:

    • WAL 中已有事务记录可以用来恢复一致状态

  • 恢复过程:

    • 重放 WAL → 修复主库

  • 一般来说,WAL 模式下:

    • 崩溃恢复效率高

    • 一致性更容易保证

可以简短总结:

WAL 模式通过把写操作先记录到独立日志文件,实现“写不阻塞多数读”,显著提升读写并发;同时也提供良好的崩溃恢复能力,通过重放 WAL 日志保证事务的持久性和一致性。


9. 多线程访问 SQLite 时,你如何管理连接和事务?

建议做法:

  1. 一个线程一个连接(推荐)

    • 每个线程拥有自己的 SQLite 连接对象(sqlite3* 或对应语言的 Connection)

    • 避免多个线程同时操作同一个连接

  2. 如果必须共享连接,外层加锁

    • 用互斥锁(mutex)包裹所有对该连接的操作:

      lock(mutex)// 使用 conn 执行 SQL
      unlock(mutex)
      
    • 保证同一时刻只有一个线程使用这个连接

  3. 配合显式事务管理

    • 在线程内明确使用 BEGIN...COMMIT/ROLLBACK 控制事务边界

    • 尽量缩短事务时间,避免长时间持有锁

  4. 结合前面提到的并发优化:

    • 开启 WAL 模式

    • 设置 busy_timeout

    • 读多写少,控制写频率

面试时可以这样说:

在多线程环境下,我通常让每个线程使用自己的 SQLite 连接,避免跨线程共享同一个连接对象。如果业务上必须共享,会在外层加 mutex 保证串行访问。事务上会显式使用 BEGIN...COMMIT 控制范围,尽量缩短事务时间,并在读取多写入少的场景下开启 WAL + busy_timeout 来提升并发能力。

http://www.dtcms.com/a/601690.html

相关文章:

  • Go语言编译原理解析 | 提升开发效率的实用指南
  • html网站完整代码天元建设集团有限公司成立时间
  • 咨询转化率涨35%,声网AI客服拯救跨境生意
  • 培训系统哪家好?TOP10企业培训系统推荐!
  • 找网站推广做网站的法律
  • 基于Gradient Boosting模型的关键驱动因素分析:Permutation、SHAP与PDP/ALE的组合方法研究
  • lockdep状态相关定义如LOCK_ENABLED_HARDIRQ
  • seo优化网站查询网站流量狂刷器
  • 网页制作门户网站案例joomla 2.5:你的网站建设_使用与管理
  • BUUCTF-Misc
  • DFS-排列数字和n皇后-java实现
  • 3.2 自注意力与多头注意力:并行计算不同特征的秘密武器
  • 宁夏建设教育协会网站如何建立公司邮箱
  • 基于昇腾 配置pytorch环境
  • 武威做网站品牌平价网站建设
  • SpringBoot19-@Qualifier用法
  • 工程公司的会计做账有哪些科目官网seo怎么做
  • C语言:一种编译器?| 深入探讨C语言编译器的工作原理与发展
  • SpringBoot+Vue智慧诊所管理系统
  • 企业网站建设价钱专业的家居行业网站开发
  • 解决Idea 插件Plantuml4idea找不到dot的问题
  • 杭州英文网站建设网站建设项目考察范文
  • 济南建设工程信息网站手机刷网站排名软件
  • docker搭建Elasticsearch+Kafka+Logstash+Filebeat日志分析系统
  • Linux离线安装Python环境
  • d47:Elasticsearch入门
  • 李宏毅机器学习笔记
  • 惠州专业网站制作公司wordpress 图片 本地
  • 毕业设计如何用dw做网站wordpress移动顶部导航菜单
  • 安科瑞Acrel-2000MG 储能能量管理系统是什么?什么场景需要用到?