私は問題があります。使い方が悪いのか問題があるのかわかりません 並行性の下では、update で実装された楽観的ロックは多くの場合、上書き書き込みが発生します 助けていただきありがとうございます~
address
簡単なテスト
オプティミスティック同時実行制御パターン ケース コード (少し変更) ドキュメント
コード デモから
スキーマ
model Seat {
id Int @id @default(autoincrement())
claimedBy String?
movieId Int
movie String
version Int
@@map("seat")
}
コード
async function testBuy(userName:string){
const movieName = 'fly'
// Find the first available seat
// availableSeat.version might be 0
const availableSeat = await prisma.seat.findFirst({
where: {
movie: movieName,
claimedBy: null,
},
})
if (!availableSeat) {
console.log('seat is zero')
return
}
//test1 and test3 use this
const seats = await prisma.seat.updateMany({
data: {
claimedBy: userName,
version: {
increment: 1,
},
},
where: {
id: availableSeat.id,
version: availableSeat.version, // This version field is the key; only claim seat if in-memory version matches database version, indicating that the field has not been updated
},
})
if (seats.count === 0) {
console.log('xxxxx count = 0')
}
//test2 and test4 use this
//const seats = await prisma.$executeRaw`update seat set claimedBy = ${userName},version =version+1 where id = ${availableSeat.id} and version = ${availableSeat.version};`
//console.log('seats=',seats)
//if (!seats) {
// console.log('xxxxx count = 0')
//}
}
function teatBuyMore(){
testBuy('userA')
testBuy('userB')
}
teatBuyMore()
テスト結果
結果は、同時実行中にテスト 1 と 3 が上書きされ、テスト 2 と 4 のみが有効になっているように見えます
トランザクション分離レベル rr
test1: db データの前: id =4 movieId=1 version = 1 movie=fly claimBy = null
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query BEGIN
prisma:query BEGIN
prisma:query SELECT `prisma_test`.`seat`.`id` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`id` = ? AND `prisma_test`.`seat`.`version` = ?)
prisma:query SELECT `prisma_test`.`seat`.`id` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`id` = ? AND `prisma_test`.`seat`.`version` = ?)
prisma:query UPDATE `prisma_test`.`seat` SET `claimedBy` = ?, `version` = (`version` + ?) WHERE `prisma_test`.`seat`.`id` IN (?)
prisma:query COMMIT
prisma:query UPDATE `prisma_test`.`seat` SET `claimedBy` = ?, `version` = (`version` + ?) WHERE `prisma_test`.`seat`.`id` IN (?)
prisma:query COMMIT
データベース データの後: id =4 movieId=1 version =3 movie=fly claimBy = userB
test2: db データの前: id =5 movieId=1 version = 1 movie=fly claimBy = null
prisma:info Starting a mysql pool with 9 connections.
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query update seat set claimedBy = ?,version = ? where id = ? and version = ?;
seats= 0
xxxxx count = 0
seats= 1
prisma:query update seat set claimedBy = ?,version = ? where id = ? and version = ?;
データベース データの後: id =5 movieId=1 version = 2 movie=fly claimBy = userB
transaction isolation level rc test3: before db data: id =6 movieId=1 version = 1 movie=fly claimBy = null
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query BEGIN
prisma:query BEGIN
prisma:query SELECT `prisma_test`.`seat`.`id` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`id` = ? AND `prisma_test`.`seat`.`version` = ?)
prisma:query SELECT `prisma_test`.`seat`.`id` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`id` = ? AND `prisma_test`.`seat`.`version` = ?)
prisma:query UPDATE `prisma_test`.`seat` SET `claimedBy` = ?, `version` = (`version` + ?) WHERE `prisma_test`.`seat`.`id` IN (?)
prisma:query COMMIT
prisma:query UPDATE `prisma_test`.`seat` SET `claimedBy` = ?, `version` = (`version` + ?) WHERE `prisma_test`.`seat`.`id` IN (?)
prisma:query COMMIT
データベース データの後: id =6 movieId=1 version =3 movie=fly claimBy = userA
test4: db データの前: id =7 movieId=1 version = 1 movie=fly claimBy = null
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query SELECT `prisma_test`.`seat`.`id`, `prisma_test`.`seat`.`claimedBy`, `prisma_test`.`seat`.`movieId`, `prisma_test`.`seat`.`movie`, `prisma_test`.`seat`.`version` FROM `prisma_test`.`seat` WHERE (`prisma_test`.`seat`.`movie` = ? AND `prisma_test`.`seat`.`claimedBy` IS NULL) LIMIT ? OFFSET ?
prisma:query update seat set claimedBy = ?,version =version+1 where id = ? and version = ?;
seats= 0
xxxxx count = 0
prisma:query update seat set claimedBy = ?,version =version+1 where id = ? and version = ?;
seats= 1
データベース データの後: id =7 movieId=1 version = 2 movie=fly claimBy = userB