Skip to content

Commit e917639

Browse files
authored
Merge pull request #10 from ydb-platform/problems-demo
Problems demo
2 parents cbc7c7d + 2cab00d commit e917639

File tree

11 files changed

+698
-0
lines changed

11 files changed

+698
-0
lines changed

problems-demo/LICENSE

Whitespace-only changes.

problems-demo/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The program simulate different typical problems of YDB-development on local ydb cluster.
2+
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
3+
*/
4+
package cmd
5+
6+
import (
7+
"context"
8+
"log"
9+
"math/rand/v2"
10+
"time"
11+
12+
"github.com/spf13/cobra"
13+
"github.com/ydb-platform/ydb-go-sdk/v3"
14+
"github.com/ydb-platform/ydb-go-sdk/v3/query"
15+
)
16+
17+
// loadWithIntervalsCmd represents the loadWithIntervals command
18+
var loadWithIntervalsCmd = &cobra.Command{
19+
Use: "loadWithIntervals",
20+
Short: "Создаёт рваную нагрузку - то есть, то - нет",
21+
Long: ``,
22+
Run: func(cmd *cobra.Command, args []string) {
23+
24+
const loadInterval = time.Minute
25+
const pauseInterval = time.Minute
26+
27+
ctx := context.Background()
28+
db := dbConnect()
29+
30+
if err := db.Query().Exec(ctx, `DROP TABLE IF EXISTS loadWithIntervals`); err != nil {
31+
log.Fatalf("Ошибка при удалении таблицы: %v", err)
32+
}
33+
34+
if err := db.Query().Exec(ctx, `
35+
CREATE TABLE loadWithIntervals (
36+
id Int64 NOT NULL,
37+
val Int64,
38+
PRIMARY KEY (id)
39+
)
40+
`); err != nil {
41+
log.Fatalf("Ошибка при создании таблицы: %v", err)
42+
}
43+
44+
for {
45+
log.Println("Нагружаю...")
46+
47+
start := time.Now()
48+
for time.Since(start) < loadInterval {
49+
db.Query().Exec(ctx, `
50+
DECLARE $id Int64;
51+
DECLARE $val Int64;
52+
53+
UPSERT INTO loadWithIntervals VALUES ($id, $val);
54+
`, query.WithParameters(ydb.ParamsFromMap(map[string]any{
55+
"id": 1,
56+
"val": rand.Int64(),
57+
})))
58+
}
59+
60+
log.Println("Пауза")
61+
time.Sleep(pauseInterval)
62+
}
63+
},
64+
}
65+
66+
func init() {
67+
rootCmd.AddCommand(loadWithIntervalsCmd)
68+
69+
// Here you will define your flags and configuration settings.
70+
71+
// Cobra supports Persistent Flags which will work for this command
72+
// and all subcommands, e.g.:
73+
// loadWithIntervalsCmd.PersistentFlags().String("foo", "", "A help for foo")
74+
75+
// Cobra supports local flags which will only run when this command
76+
// is called directly, e.g.:
77+
// loadWithIntervalsCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
78+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
/*
2+
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
3+
*/
4+
package cmd
5+
6+
import (
7+
"context"
8+
"log"
9+
"time"
10+
11+
"github.com/spf13/cobra"
12+
"github.com/ydb-platform/ydb-go-sdk/v3"
13+
"github.com/ydb-platform/ydb-go-sdk/v3/query"
14+
)
15+
16+
// longTransactionCmd represents the longTransaction command
17+
var longTransactionCmd = &cobra.Command{
18+
Use: "longTransaction",
19+
Short: "Демонстрирует длительные конфликтующие транзакции",
20+
Long: ``,
21+
Run: func(cmd *cobra.Command, args []string) {
22+
ctx := context.Background()
23+
db := dbConnect()
24+
25+
_ = db.Query().Exec(ctx, "DROP TABLE IF EXISTS longTransaction")
26+
if err := db.Query().Exec(ctx, "CREATE TABLE longTransaction (id Int64, val Int64, PRIMARY KEY(id));"); err != nil {
27+
log.Fatal("Ошибка при создании таблицы", err)
28+
}
29+
30+
if err := db.Query().Exec(ctx, "INSERT INTO longTransaction (id, val) VALUES (1, 0)"); err != nil {
31+
log.Fatal("Ошибка при добавлении начальной строки таблицы", err)
32+
}
33+
34+
i := 0
35+
for {
36+
i++
37+
goroutineNum := i
38+
go func() {
39+
attempt := 0
40+
err := db.Query().Do(ctx, func(ctx context.Context, s query.Session) error {
41+
attempt++
42+
43+
// тут я создаю транзакцию явно вместо использования DoTx
44+
// чтобы иметь возможность явно получить ошибку и вывести её в лог
45+
tx, err := s.Begin(ctx, query.TxSettings(query.WithDefaultTxMode()))
46+
if err != nil {
47+
return err
48+
}
49+
50+
res, err := tx.QueryRow(ctx, "SELECT val FROM longTransaction WHERE id = 1")
51+
if err != nil {
52+
return err
53+
}
54+
55+
var old int64
56+
if err = res.Scan(&old); err != nil {
57+
return err
58+
}
59+
60+
time.Sleep(2 * time.Second)
61+
newVal := old + 1
62+
err = tx.Exec(ctx, `
63+
DECLARE $val AS Int64;
64+
65+
UPSERT INTO longTransaction (id, val) VALUES (1, $val)
66+
`, query.WithParameters(
67+
ydb.ParamsFromMap(map[string]any{"$val": newVal}),
68+
), query.WithCommit())
69+
var updateResult = "OK"
70+
if err != nil {
71+
// Сообщения об ошибках очень длинные и подробные - для диагностики
72+
// поэтому интересующую в демонстрации ошибку я сокращу - для наглядности
73+
if ydb.IsOperationErrorTransactionLocksInvalidated(err) {
74+
updateResult = "TLI"
75+
} else {
76+
updateResult = err.Error()
77+
}
78+
}
79+
log.Printf("goroutine: %v, val:%v, result: %v", goroutineNum, newVal, updateResult)
80+
return err
81+
})
82+
log.Printf("retry completed for goroutine: %v, attempts: %v, result: %v", goroutineNum, attempt, err)
83+
}()
84+
time.Sleep(time.Second)
85+
}
86+
},
87+
}
88+
89+
func init() {
90+
rootCmd.AddCommand(longTransactionCmd)
91+
92+
// Here you will define your flags and configuration settings.
93+
94+
// Cobra supports Persistent Flags which will work for this command
95+
// and all subcommands, e.g.:
96+
// longTransactionCmd.PersistentFlags().String("foo", "", "A help for foo")
97+
98+
// Cobra supports local flags which will only run when this command
99+
// is called directly, e.g.:
100+
// longTransactionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
101+
}

problems-demo/cmd/manyIndexes.go

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/*
2+
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
3+
*/
4+
package cmd
5+
6+
import (
7+
"context"
8+
"log"
9+
"math/rand/v2"
10+
11+
"github.com/spf13/cobra"
12+
"github.com/ydb-platform/ydb-go-sdk/v3"
13+
"github.com/ydb-platform/ydb-go-sdk/v3/query"
14+
)
15+
16+
// manyIndexesCmd represents the manyIndexes command
17+
var manyIndexesCmd = &cobra.Command{
18+
Use: "manyIndexes",
19+
Short: "Создаёт таблицу с большим количеством индексов и добавляет туда строки",
20+
Long: ``,
21+
Run: func(cmd *cobra.Command, args []string) {
22+
ctx := context.Background()
23+
db := dbConnect()
24+
25+
if err := db.Query().Exec(ctx, "DROP TABLE IF EXISTS many_indexes;"); err != nil {
26+
log.Fatalf("Ошибка при удалении таблицы: %v", err)
27+
}
28+
29+
if err := db.Query().Exec(ctx, `
30+
CREATE TABLE many_indexes (
31+
id Int64 NOT NULL,
32+
val1 Int64,
33+
val2 Int64,
34+
val3 Int64,
35+
PRIMARY KEY (id),
36+
INDEX i1 GLOBAL ON (val1),
37+
INDEX i12 GLOBAL ON (val1, val2),
38+
INDEX i13 GLOBAL ON (val1, val3),
39+
INDEX i123 GLOBAL ON (val1, val2, val3),
40+
INDEX i132 GLOBAL ON (val1, val3, val2),
41+
INDEX i2 GLOBAL ON (val2),
42+
INDEX i21 GLOBAL ON (val2, val1),
43+
INDEX i213 GLOBAL ON (val2, val1, val3),
44+
INDEX i23 GLOBAL ON (val2, val3),
45+
INDEX i231 GLOBAL ON (val2, val3, val1),
46+
INDEX i3 GLOBAL ON (val3),
47+
INDEX i31 GLOBAL ON (val3, val1),
48+
INDEX i312 GLOBAL ON (val3, val1, val2),
49+
INDEX i32 GLOBAL ON (val3, val2),
50+
INDEX i321 GLOBAL ON (val3, val2, val1),
51+
)
52+
`); err != nil {
53+
log.Fatalf("Ошибка при создании таблицы: %v", err)
54+
}
55+
56+
log.Println("Начинаю заполнять строки")
57+
for i := 0; ; i++ {
58+
err := db.Query().Exec(ctx, `
59+
DECLARE $id AS Int64;
60+
DECLARE $val1 AS Int64;
61+
DECLARE $val2 AS Int64;
62+
DECLARE $val3 AS Int64;
63+
64+
UPSERT INTO many_indexes (id, val1, val2, val3)
65+
VALUES ($id, $val1, $val2, $val3);
66+
`, query.WithParameters(ydb.ParamsFromMap(map[string]any{
67+
"$id": rand.Int64(),
68+
"$val1": rand.Int64(),
69+
"$val2": rand.Int64(),
70+
"$val3": rand.Int64(),
71+
"$val4": rand.Int64(),
72+
})))
73+
if err != nil {
74+
log.Fatalf("Ошибка при добавлении строки: %v", err)
75+
}
76+
}
77+
},
78+
}
79+
80+
func init() {
81+
rootCmd.AddCommand(manyIndexesCmd)
82+
83+
// Here you will define your flags and configuration settings.
84+
85+
// Cobra supports Persistent Flags which will work for this command
86+
// and all subcommands, e.g.:
87+
// manyIndexesCmd.PersistentFlags().String("foo", "", "A help for foo")
88+
89+
// Cobra supports local flags which will only run when this command
90+
// is called directly, e.g.:
91+
// manyIndexesCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
92+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright © 2025 NAME HERE <EMAIL ADDRESS>
3+
*/
4+
package cmd
5+
6+
import (
7+
"context"
8+
"fmt"
9+
"log"
10+
"strconv"
11+
"sync/atomic"
12+
"time"
13+
14+
"github.com/spf13/cobra"
15+
)
16+
17+
// oftenCompilationCmd represents the oftenCompilation command
18+
var oftenCompilationCmd = &cobra.Command{
19+
Use: "oftenCompilation",
20+
Short: "Эта команда отправляет на сервер много разных по тексту запросов",
21+
Long: ``,
22+
Run: func(cmd *cobra.Command, args []string) {
23+
ctx := context.Background()
24+
db := dbConnect()
25+
26+
i := int64(0)
27+
for range 4 {
28+
go func() {
29+
for {
30+
q := "SELECT " + strconv.FormatInt(atomic.AddInt64(&i, 1), 10)
31+
_, err := db.Query().QueryRow(ctx, q)
32+
if err != nil {
33+
log.Printf("query error: %v", err)
34+
time.Sleep(time.Second)
35+
}
36+
}
37+
}()
38+
}
39+
40+
for {
41+
time.Sleep(time.Second)
42+
fmt.Println("Выполнено запросов:", i)
43+
}
44+
},
45+
}
46+
47+
func init() {
48+
rootCmd.AddCommand(oftenCompilationCmd)
49+
50+
// Here you will define your flags and configuration settings.
51+
52+
// Cobra supports Persistent Flags which will work for this command
53+
// and all subcommands, e.g.:
54+
// oftenCompilationCmd.PersistentFlags().String("foo", "", "A help for foo")
55+
56+
// Cobra supports local flags which will only run when this command
57+
// is called directly, e.g.:
58+
// oftenCompilationCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
59+
}

0 commit comments

Comments
 (0)