# mongo update 鎖測試
https://hub.docker.com/r/bitnami/mongodb-sharded/
```
func UseSessionNoSleep(client *mongo.Client, userID int) {
ctx := context.Background()
collection := client.Database("yolo").Collection("user")
session, err := client.StartSession()
if err != nil {
log.Fatal(err)
}
result, err := session.WithTransaction(ctx, func(sCtx mongo.SessionContext) (interface{}, error) {
objID, _ := primitive.ObjectIDFromHex("61ef6bd8a6c0946e9484b3a9")
result, err := collection.UpdateOne(sCtx, bson.D{{"_id", objID}, {"age", bson.D{{"$gt", 0}}}}, bson.D{{"$inc", bson.D{{"age", -1}}}})
if err != nil {
return nil, err
}
return result, nil
})
if err != nil {
fmt.Printf("userID:%d err:%s\n", userID, err)
}
fmt.Printf("userID:%d result:%v\n", userID, result)
}
func UseSessionHasSleep(client *mongo.Client, userID int) {
ctx := context.Background()
collection := client.Database("yolo").Collection("user")
session, err := client.StartSession()
if err != nil {
log.Fatal(err)
}
result, err := session.WithTransaction(ctx, func(sCtx mongo.SessionContext) (interface{}, error) {
objID, _ := primitive.ObjectIDFromHex("61ef6bd8a6c0946e9484b3a9")
result, err := collection.UpdateOne(sCtx, bson.D{{"_id", objID}, {"age", bson.D{{"$gt", 0}}}}, bson.D{{"$inc", bson.D{{"age", -1}}}})
if err != nil {
rand.Seed(time.Now().UnixNano())
d := time.Second * time.Duration(rand.Intn(20))
time.Sleep(d)
return nil, err
}
return result, nil
})
if err != nil {
fmt.Printf("userID:%d err:%s\n", userID, err)
}
fmt.Printf("userID:%d result:%v\n", userID, result)
}
func UpdateWithoutSession(client *mongo.Client, userID int) {
ctx := context.Background()
collection := client.Database("yolo").Collection("user")
objID, _ := primitive.ObjectIDFromHex("61ef6bd8a6c0946e9484b3a9")
result, err := collection.UpdateOne(ctx, bson.D{{"_id", objID}, {"age", bson.D{{"$gt", 0}}}}, bson.D{{"$inc", bson.D{{"age", -1}}}})
if err != nil {
fmt.Printf("userID:%d err:%s\n", userID, err)
}
fmt.Printf("userID:%d result:%v\n", userID, result)
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := mongo.Connect(
ctx,
options.Client().ApplyURI("mongodb://localhost:27017"),
options.Client().SetAuth(options.Credential{
Username: "root",
Password: "password123",
}),
)
if err != nil {
log.Fatal(err)
}
defer func() { _ = client.Disconnect(ctx) }()
var wg sync.WaitGroup
maxNum := 1000
wg.Add(maxNum)
now := time.Now()
// 初始庫存為 100, 1000 人同時搶
for i := 0; i < maxNum; i++ {
go func(userID int) {
defer wg.Done()
// 沒有辦法執行完
//UseSessionNoSleep(client, userID)
// 約 25 秒
//UseSessionHasSleep(client, userID)
// 約 2 秒
UpdateWithoutSession(client, userID)
}(i)
}
wg.Wait()
fmt.Printf("operation finished cost %s\n", time.Since(now).String())
fmt.Println()
}
```