如何在MongoDB中锁定收藏

9avjhtql  于 2023-03-17  发布在  Go
关注(0)|答案(4)|浏览(133)

我的数据库里有个收藏
1.我想在用户更新文档时锁定我的收藏
2.为其他用户更新集合时未执行任何操作预期读取
请给予如何在MongoDB中锁定集合的建议
致上
广州体育学院

ql3eal8s

ql3eal8s1#

MongoDB已经实现了一个writergreedy数据库级锁。
这意味着当特定文档被写入时:

  • User集合将被锁定
  • 在写入数据之前,将无法进行读取

无法读取的原因是MongoDB无法在写入时进行一致的读取(该死的物理,你又赢了)。
值得注意的是,如果您想要一个更复杂的锁,跨越多行,那么MongoDB中将不提供这种锁,并且没有实现这种锁的真实的方法。

b1zrtrql

b1zrtrql2#

MongoDB锁已经为您做到了这一点。看看哪些操作获取了哪些锁,每个锁意味着什么。

67up9zun

67up9zun3#

请参阅MongoDB文档中关于写操作的部分,特别注意这一节:
隔离写操作
对单个文档的修改总是原子的,即使写操作修改了该文档中的多个子文档。对于修改多个文档的写操作,该操作作为一个整体不是原子的,其他操作可以交叉进行。
没有其他操作是原子的。但是,您可以尝试使用隔离操作符隔离影响多个文档的写操作。
要将写操作序列与其他读写操作隔离,请参阅执行〉两阶段提交。

3hvapo4f

3hvapo4f4#

我读了mongo的文档,但我找不到任何容易使用和维护我的项目,所以我得到了这个想法,实际上是工作得很好,它是超级简单,易于使用。

  • 首先定义一个Lock模型,其中_id是集合的名称
import pkg from 'mongoose';                                         
 const {Schema, model} = pkg;                                        
 const lockSchema = new Schema(
 {
     _id: {
         type: String,
         required: true
     },
     isLocked: {
         type: Boolean,
         required: true
     }
 },
 {timestamps: true}                                               
 );                                                                 
 export const Lock = model('Lock', lockSchema, 'locks');
  • 然后定义一个中间件,可以检查感兴趣的集合是否被锁定(在这种情况下,只返回一个错误,但是可以将请求存储在队列中,以便在集合不再被锁定时处理请求)
import {Lock} from "../models/Lock.js";                            

 export const USERS_COLLECTION= 'users';                   

 export const lock = async (req, res, next) => {                     

 const {isLocked} = await Lock.findById(USERS_COLLECTION);   
 if (isLocked) {
     return res.status(409).send('operation not available for possible 
 conflict states, retry in a few seconds'); }                                                                   

 next();                                                                 
 }
  • 最后,在路由器函数中,当您有多个读写操作存在并发问题时,您在第一个IO操作之前锁定集合,并在发送回响应之前或catch块出错时解锁集合
router.post('/users', lock, (req, res) => {                                   

try{                                                                    
    await Lock.findByIdAndUpdate(USERS_COLLECTION, {isLocked: true});

     // multiple read/write operations on user collection                                                                                                                           

    await Lock.findByIdAndUpdate(USERS_COLLECTION, {isLocked: false});                                                                    
    res.send();                                                                                                                   
  }                                                               

catch {                                                                                                                             
    await Lock.findByIdAndUpdate(USERS_COLLECTION, {isLocked: false});                                                   

    res.status(500).send();                                                                    
  }                                                          

})

相关问题