副本集mongo中,在没有指定读取策略的情况下,默认到primary读取
主要控制客户端driver从副本集(Replica Set)读数据的时候如何路由
各个配置值的含义如下:
mongodb+srv://xxx.com?ssl=false&retryWrites=true&w=majority&readConcernLevel=majority&readPreference=secondaryPreferred
mongo的upsert命令【不是】原子的,upsert 分为两步:
在使用该功能时,需考虑fifter条件是否作唯一, 在并发下,多个线程或协程同时 upsert 并完成找数据这一步操作,此时这些线程都没有找到数据,然后都进行插入数据的操作,于是重复数据便产生了;
解决这一问题的方案有两种种:
1、一种是给表加唯一索引
2、给执行upsert 操作加上一个写锁,
大多数情况下,我们采用第一种,在代码上线前,先执行唯一索引
db.$collection.createIndex($unique_keys, { backgroud : true, unique : true}),如果不加【unique : true】则为普通索引,解决不了并发重复的问题
mongo在指定读写分离时,即 readPreference=secondaryPreferred或者readPreference=secondary时, 在代码中开启事务时,事务的sessionContext不能用于查询,事务的读只能在主库处理,否则会报错误【 read preference in a transaction must be primary】, 如果事务中没有读取操作,则不存在该问题
为了在读取操作也使用事务功能, 需要在开启事务时指定主库操作,后面就可以在读取时,使用事务的sessionContext,如下
opts := &options.TransactionOptions{ReadPreference: readpref.Primary()}
sessionContext.StartTransaction(opts)
ctx := context.Background()
client := mongo.GetClient(constant.DBPrefix)
err := client.UseSession(ctx, func(sessionContext m.SessionContext) error {
opts := &options.TransactionOptions{ReadPreference: readpref.Primary()}
//关键代码,如果事务中全是写入操作,此处不必指定
err := sessionContext.StartTransaction(opts)
// 后续的db操作要用事务就用sessionContext
// 不用事务就用ctx,正常情况下,开启事务后,里面的db操作都应该使用事务的sessionContext
//err = mongo.MongoDBCurd(constant.DBPrefix, mongomodel.MyCollectionName).Find(ctx, query, &list) //无事务读取
err = mongo.MongoDBCurd(constant.DBPrefix, mongomodel.MyCollectionName).Find(sessionContext, query, &list)
//有事务的读取
if err != nil {
_ = sessionContext.AbortTransaction(sessionContext)
return err
}
_ = sessionContext.CommitTransaction(sessionContext)
return nil
})
https://www.mongodb.com/docs/manual/core/read-preference
https://www.mongodb.com/zh-cn/docs/manual/core/read-preference/
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。