全部学科
Python全栈
python
NodeJS全栈
nodejs

高级并发与锁机制专题测试

20 题 50 分钟 难度:★★★

考察知识点

  • 乐观锁与版本号机制
  • 悲观锁与 SELECT FOR UPDATE
  • 行级锁与表级锁
  • 并发安全与竞态条件
💡 参考答案在文末
判断题
1

使用 Version 字段的乐观锁可以完全避免 ABA 问题。

A

B

2

在 InnoDB 存储引擎中,SELECT FOR UPDATE 一定只锁定查询条件匹配的行,不会影响其他行。

A

B

单选题
3

当乐观锁更新失败时,最佳的重试策略是什么?

A

无限循环重试,直到成功

B

放弃更新,返回错误由上层处理

C

有限次数重试(如3次),每次带随机退避时间,超过次数后返回错误

D

立即重试,不加任何延迟

4

在 GORM 中,如何对查询记录加行级排他锁(SELECT FOR UPDATE)?

A

db.Where("id = ?", 1).Locking("FOR UPDATE").First(&user)

B

db.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", 1).First(&user)

C

db.Raw("SELECT * FROM users WHERE id = 1 FOR UPDATE").Scan(&user)

D

db.Where("id = ?", 1).First(&user, clauselocking.Update)

5

如果一个记录需要同时基于 Version 和 Status 字段做乐观锁控制(确保只更新状态为 "pending" 的记录),应该如何写?

A

db.Where("id = ? AND version = ? AND status = ?", id, version, "pending").Updates(...)

B

需要分别检查,无法合并为一个 WHERE 条件

C

db.Where("id = ?", id).Where("version = ? OR status = ?", version, "pending").Updates(...)

D

db.Clauses(clause.Locking{Strength: "UPDATE"}).Where("id = ?", id).Updates(...)

6

在事务中使用乐观锁时,版本号检查应该在什么时候执行?

A

事务开始时读取数据的同时记录版本号

B

事务提交时再检查版本号

C

每次更新数据时检查版本号,并在事务提交前确认所有更新成功

D

事务回滚时检查

7

在 MySQL 8.0+ 中,如何跳过已被锁定的行,只查询未被锁定的行?

A

db.Clauses(clause.Locking{Strength: "UPDATE", Options: "SKIP LOCKED"}).Find(&records)

B

db.Where("locked = false").Find(&records)

C

无法实现,必须使用乐观锁

D

db.Clauses(clause.Locking{Strength: "SHARE"}).Find(&records)

8

在 GORM 中,如何对查询加共享锁(SELECT FOR SHARE)?

A

db.Clauses(clause.Locking{Strength: "SHARE"}).Where("id = ?", 1).First(&user)

B

db.Clauses(clause.Locking{Strength: "READ"}).Where("id = ?", 1).First(&user)

C

db.Where("id = ?", 1).First(&user, gorm.ShareLock)

D

db.Lock("SHARE").Where("id = ?", 1).First(&user)

9

乐观锁的核心思想是什么?

A

在读取数据时立即加排他锁,阻止其他事务访问

B

假设并发冲突很少发生,在更新时检查数据是否被其他事务修改过

C

使用数据库的表级锁保证一致性

D

在事务开始时复制所有数据到临时表

10

当一个事务等待获取悲观锁时,如果另一个持有锁的事务长时间不释放,会发生什么?

A

等待事务会立即报错

B

等待事务会一直阻塞,直到数据库的锁等待超时设置(lock_wait_timeout)触发

C

GORM 会自动超时并释放

D

数据库会自动升级锁为表级锁

多选题
11

以下哪些场景适合使用悲观锁?

A

库存扣减:多个并发请求同时扣减同一商品库存

B

用户信息查询:多个用户同时查看同一用户资料

C

账户余额转账:从一个账户扣款同时向另一个账户加款

D

计数器自增:页面访问次数统计

12

在 GORM 中,实现乐观锁的方式有哪些?

A

在模型中添加 Version 字段,更新时检查版本号

B

使用 GORM 的 OptimisticLock plugin

C

在 WHERE 条件中加入版本号作为更新条件,检查 Affected Rows

D

使用 UpdatedAt 时间戳判断是否被修改

13

在高并发场景下,过度使用悲观锁可能导致哪些问题?

A

事务串行化执行,系统吞吐量大幅下降

B

锁等待超时错误频发

C

死锁概率增加

D

数据库连接池耗尽

14

在以下哪些场景中,乐观锁比悲观锁更合适?

A

商品详情页浏览量统计(高并发读,低并发写)

B

商品库存扣减(高并发写)

C

用户资料编辑(低并发,冲突率低)

D

订单状态流转(中等并发,状态必须严格一致)

15

与悲观锁相比,乐观锁有哪些性能优势?

A

读取操作不会阻塞其他事务,并发读取性能更高

B

不需要数据库层面的锁等待,减少连接占用时间

C

在冲突率高的场景下,重试开销低于悲观锁的排队等待

D

不需要特殊数据库支持,普通 UPDATE 即可实现

16

关于悲观锁与数据库事务隔离级别的关系,以下哪些描述是正确的?

A

SELECT FOR UPDATE 在所有隔离级别下都能正常工作

B

在 READ COMMITTED 隔离级别下,使用 FOR UPDATE 可以防止脏读和不可重复读

C

FOR UPDATE 锁会在事务提交后自动释放

D

FOR UPDATE 可以防止其他事务对同一行执行 UPDATE 或 DELETE

填空题
17

使用 Version 字段实现乐观锁:

Go
type Product struct {
    ID      uint
    Stock   int
    Version int `____________`
}

func UpdateStock(db *gorm.DB, id uint, deduct int, currentVersion int) error {
    result := db.Model(&Product{}).
        Where("id = ? AND ____________ = ?", id, currentVersion).
        Updates(map[string]interface{}{
            "stock":   gorm.Expr("stock - ?", deduct),
            "version": gorm.Expr("version + ____________"),
        })
    if result.RowsAffected == 0 {
        return errors.New("数据已被其他事务修改")
    }
    return nil
}
18

使用悲观锁扣减库存:

Go
db.!!1_Transaction!!(func(tx *gorm.DB) error {
    var product Product
    tx.Clauses(clause.Locking{!!2_Strength!!: "UPDATE"}).
        Where("id = ?", productID).First(&product)
    if product.Stock < quantity {
        return errors.New("库存不足")
    }
    product.Stock -= quantity
    return tx.!!3_Save!!(&product).Error
})
简答题
19

设计一个基于悲观锁的库存扣减系统,需要处理以下要求:

  1. 支持批量扣减(一次扣减多种商品)
  2. 防止超卖
  3. 避免死锁
  4. 设置合理的锁超时

请给出完整的代码实现,并说明如何避免死锁。

20

请实现一个通用的乐观锁重试函数,要求:

  1. 支持自定义最大重试次数
  2. 带指数退避策略
  3. 接受一个包含读取-修改-更新逻辑的回调函数
  4. 返回最终的错误或成功结果
参考答案
1.正确 2.错误 3.C 4.B 5.A 6.C 7.A 8.A 9.B 10.B 11.A;C 12.A;C;D 13.A;B;C;D 14.A;C 15.A;B;D 16.B;C;D 17.gorm:"default:1";version;1 18.Transaction;Strength;Save 19. 20.
想在手机上练习这套试卷?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码
← 上一套试卷 错误处理与日志专题测试
下一套试卷 → 高级查询技术专题测试
扫码体验小程序
加载中
想在手机上刷题学习?
使用微信卷王开发者小程序,打开首页顶部扫码功能识别二维码