diff --git a/internal/model/voice_room_red_packet_models.go b/internal/model/voice_room_red_packet_models.go index 66dcaf1..3769901 100644 --- a/internal/model/voice_room_red_packet_models.go +++ b/internal/model/voice_room_red_packet_models.go @@ -76,12 +76,12 @@ func (VoiceRoomRedPacket) TableName() string { return "voice_room_red_packet" } // VoiceRoomRedPacketSlice 保存红包预拆分份额。 type VoiceRoomRedPacketSlice struct { - ID int64 `gorm:"column:id;primaryKey"` - PacketID int64 `gorm:"column:packet_id;uniqueIndex:uk_voice_room_red_packet_slice,priority:1;index:idx_voice_room_red_packet_slice_claim,priority:1"` + ID int64 `gorm:"column:id;primaryKey;index:idx_voice_room_red_packet_slice_claim_order,priority:4"` + PacketID int64 `gorm:"column:packet_id;uniqueIndex:uk_voice_room_red_packet_slice,priority:1;index:idx_voice_room_red_packet_slice_claim,priority:1;index:idx_voice_room_red_packet_slice_claim_order,priority:1"` PacketNo string `gorm:"column:packet_no;size:64"` - SortNo int `gorm:"column:sort_no;uniqueIndex:uk_voice_room_red_packet_slice,priority:2"` + SortNo int `gorm:"column:sort_no;uniqueIndex:uk_voice_room_red_packet_slice,priority:2;index:idx_voice_room_red_packet_slice_claim_order,priority:3"` Amount int64 `gorm:"column:amount"` - Status string `gorm:"column:status;size:32;index:idx_voice_room_red_packet_slice_claim,priority:2"` + Status string `gorm:"column:status;size:32;index:idx_voice_room_red_packet_slice_claim,priority:2;index:idx_voice_room_red_packet_slice_claim_order,priority:2"` ClaimUserID *int64 `gorm:"column:claim_user_id"` ClaimRecordID *int64 `gorm:"column:claim_record_id"` CreateTime time.Time `gorm:"column:create_time"` diff --git a/internal/service/voiceroomredpacket/claim.go b/internal/service/voiceroomredpacket/claim.go index ec80332..4f83ce7 100644 --- a/internal/service/voiceroomredpacket/claim.go +++ b/internal/service/voiceroomredpacket/claim.go @@ -182,6 +182,12 @@ func (s *Service) completeClaimWallet(ctx context.Context, claim model.VoiceRoom } now := time.Now() if err := s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + var lockedPacket model.VoiceRoomRedPacket + if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}). + Where("id = ?", claim.PacketID). + First(&lockedPacket).Error; err != nil { + return err + } if err := tx.Model(&model.VoiceRoomRedPacketClaim{}). Where("id = ?", claim.ID). Updates(map[string]any{ @@ -200,7 +206,7 @@ func (s *Service) completeClaimWallet(ctx context.Context, claim model.VoiceRoom return err } return tx.Model(&model.VoiceRoomRedPacket{}). - Where("id = ? AND remain_count = 0 AND status = ?", claim.PacketID, packetStatusActive). + Where("id = ? AND remain_count = 0 AND status = ?", lockedPacket.ID, packetStatusActive). Updates(map[string]any{ "status": packetStatusFinished, "update_time": now, diff --git a/migrations/050_voice_room_red_packet_slice_claim_order_index.sql b/migrations/050_voice_room_red_packet_slice_claim_order_index.sql new file mode 100644 index 0000000..ddf08ab --- /dev/null +++ b/migrations/050_voice_room_red_packet_slice_claim_order_index.sql @@ -0,0 +1,29 @@ +SET @current_schema := DATABASE(); + +SET @voice_room_red_packet_slice_claim_order_idx_columns := ( + SELECT GROUP_CONCAT(column_name ORDER BY seq_in_index) + FROM information_schema.statistics + WHERE table_schema = @current_schema + AND table_name = 'voice_room_red_packet_slice' + AND index_name = 'idx_voice_room_red_packet_slice_claim_order' +); + +SET @drop_voice_room_red_packet_slice_claim_order_idx_sql := IF( + @voice_room_red_packet_slice_claim_order_idx_columns IS NOT NULL + AND @voice_room_red_packet_slice_claim_order_idx_columns <> 'packet_id,status,sort_no,id', + 'ALTER TABLE `voice_room_red_packet_slice` DROP INDEX `idx_voice_room_red_packet_slice_claim_order`', + 'SELECT 1' +); +PREPARE drop_voice_room_red_packet_slice_claim_order_idx_stmt FROM @drop_voice_room_red_packet_slice_claim_order_idx_sql; +EXECUTE drop_voice_room_red_packet_slice_claim_order_idx_stmt; +DEALLOCATE PREPARE drop_voice_room_red_packet_slice_claim_order_idx_stmt; + +SET @add_voice_room_red_packet_slice_claim_order_idx_sql := IF( + @voice_room_red_packet_slice_claim_order_idx_columns IS NULL + OR @voice_room_red_packet_slice_claim_order_idx_columns <> 'packet_id,status,sort_no,id', + 'ALTER TABLE `voice_room_red_packet_slice` ADD INDEX `idx_voice_room_red_packet_slice_claim_order` (`packet_id`, `status`, `sort_no`, `id`)', + 'SELECT 1' +); +PREPARE add_voice_room_red_packet_slice_claim_order_idx_stmt FROM @add_voice_room_red_packet_slice_claim_order_idx_sql; +EXECUTE add_voice_room_red_packet_slice_claim_order_idx_stmt; +DEALLOCATE PREPARE add_voice_room_red_packet_slice_claim_order_idx_stmt;