2020-04-08 19:20:23 +00:00
|
|
|
|
database/sql
|
2021-04-08 13:41:48 +00:00
|
|
|
|
Лекция 9
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
Синельников Илья
|
|
|
|
|
|
|
|
|
|
* Способы работы с базами данных
|
|
|
|
|
|
|
|
|
|
- database/sql - любые SQL базы данных
|
|
|
|
|
- всё остальное
|
|
|
|
|
|
|
|
|
|
* database/sql
|
|
|
|
|
|
|
|
|
|
- абстракция для работы с SQL базами данных
|
|
|
|
|
- набор интерфейсов для написания драйверов
|
2021-04-08 13:41:48 +00:00
|
|
|
|
- нет продвинутых возможностей (например, батчинг)
|
|
|
|
|
- драйверы часто имеют расширенный API
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
.code sql/driver.go /^type Driver/,/^}/
|
|
|
|
|
.code sql/driver.go /^type QueryerContext/,/^}/
|
|
|
|
|
|
2020-04-09 13:18:49 +00:00
|
|
|
|
* Подключение - database/sql
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:18:49 +00:00
|
|
|
|
.code open/sql.go
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:18:49 +00:00
|
|
|
|
* Подключение - на прямую
|
|
|
|
|
|
|
|
|
|
.code open/pgx.go
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Основные сущности
|
|
|
|
|
|
|
|
|
|
- DB - connection pool к базе
|
2021-04-08 13:41:48 +00:00
|
|
|
|
- Rows - результат запроса
|
2020-04-08 19:20:23 +00:00
|
|
|
|
- Row - одна строка из результата запроса
|
|
|
|
|
- Null* - типы для работы с Null значениями
|
|
|
|
|
- Tx - транзакция
|
|
|
|
|
- Conn - одно подключение к базе
|
2021-04-08 13:41:48 +00:00
|
|
|
|
- Stmt - подготовленый запрос
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Проверка доступности
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code alive/ping.go /^func IsItAliveQuestionMark/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Запрос с получением результатов
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code query/query.go /^func Query/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Запрос с получением одного результата
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code query/queryrow.go /^func QueryRow/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Запрос без результатов
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code exec/exec.go /^func Exec/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
Возвращаемый тип
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code exec/result.go /^type Result/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
* Именованые аргументы
|
|
|
|
|
- реализуются на уровне драйвера
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code named/named.go /^type NamedArg/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
* Именованые аргументы - использование
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code named/insert.go /^func Insert/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
* Nulls
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code nulls/nulls.go /^type NullString/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
* Null в аргументах
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code nulls/insert.go /^func Insert/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
Передаём значения
|
|
|
|
|
.code nulls/insert.go /^func DoStuff/,/^}/
|
|
|
|
|
|
|
|
|
|
* Null в результатах
|
|
|
|
|
.code nulls/rows.go /^func Results/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Работа с конкретным подключением к БД
|
2021-04-08 11:32:08 +00:00
|
|
|
|
|
|
|
|
|
.code conn/conn.go /^func Conn/,/^}/
|
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Работа с транзакциями
|
2021-04-08 11:32:08 +00:00
|
|
|
|
|
|
|
|
|
.code tx/tx.go /^func Begin/,/^}/
|
|
|
|
|
|
2020-04-08 19:20:23 +00:00
|
|
|
|
* Prepared Statements
|
|
|
|
|
|
|
|
|
|
Плюсы:
|
2021-04-08 19:34:22 +00:00
|
|
|
|
|
2020-04-08 19:20:23 +00:00
|
|
|
|
- решают проблему sql-injection
|
|
|
|
|
- производительность
|
|
|
|
|
|
|
|
|
|
Минусы:
|
2021-04-08 19:34:22 +00:00
|
|
|
|
|
2020-04-08 19:20:23 +00:00
|
|
|
|
- удобство
|
|
|
|
|
- производительность
|
2021-04-08 13:41:48 +00:00
|
|
|
|
- несовместимы с некоторыми режимами работы пулеров коннектов
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Prepare
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code prepare/prepare.go /^func Prepare/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:37:21 +00:00
|
|
|
|
* Настройка *sql.DB
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
- func (db *DB) SetConnMaxIdleTime(d time.Duration)
|
|
|
|
|
- func (db *DB) SetConnMaxLifetime(d time.Duration)
|
|
|
|
|
- func (db *DB) SetMaxIdleConns(n int)
|
|
|
|
|
- func (db *DB) SetMaxOpenConns(n int)
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:37:21 +00:00
|
|
|
|
* Статистика *sql.DB
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
- func (db *DB) Stats() DBStats
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
.code conf/stats.go /^type DBStats/,/^}
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
* Подводные камни при работе с database/sql
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
* Основные типы граблей
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
- неосвобождение ресурсов
|
2021-04-08 11:32:08 +00:00
|
|
|
|
- дедлоки
|
|
|
|
|
- нюансы каждого отдельного драйвера
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Context - вечные запросы
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
.code resources/ctx.go /^func NoContext/,/^}/
|
2020-04-09 13:00:41 +00:00
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Запросы - неосвобождение ресурсов
|
2020-04-09 13:00:41 +00:00
|
|
|
|
|
|
|
|
|
.code resources/rows.go /^func RowsExhaust/,/^}/
|
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Коннекты - неосвобождение ресурсов
|
2021-04-08 11:32:08 +00:00
|
|
|
|
|
|
|
|
|
.code resources/conn.go /^func ConnExhaust/,/^}/
|
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Транзакции - неосвобождение ресурсов
|
2020-04-09 13:00:41 +00:00
|
|
|
|
|
|
|
|
|
.code resources/tx.go /^func TxExhaust/,/^}/
|
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Транзакции - исчерпание ресурсов приводящее к deadlock
|
2020-04-09 13:00:41 +00:00
|
|
|
|
|
|
|
|
|
.code resources/tx.go /^func TxDeadlock/,/^}/
|
|
|
|
|
|
2021-04-08 13:41:48 +00:00
|
|
|
|
* Запросы - исчерпание ресурсов приводящее к deadlock
|
2020-04-09 13:00:41 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
.code resources/queries.go /^func QueryDeadlock/,/^}/
|
|
|
|
|
|
|
|
|
|
* Запросы - deadlock - fix 1
|
|
|
|
|
|
|
|
|
|
.code resources/queries.go /^func QueryDeadlockFixOne/,/^}/
|
|
|
|
|
|
|
|
|
|
* Запросы - deadlock - fix 2
|
|
|
|
|
|
|
|
|
|
.code resources/queries.go /^func QueryDeadlockFixTwo/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Удобства и расширения
|
|
|
|
|
|
|
|
|
|
* github.com/jmoiron/sqlx
|
|
|
|
|
|
|
|
|
|
- drop-in replacement для database/sql
|
|
|
|
|
- добавляет множество вспомогательных методов
|
2021-04-08 19:34:22 +00:00
|
|
|
|
- реализует именованные аргументы
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* sqlx - подключение
|
|
|
|
|
|
|
|
|
|
.code sqlx/open.go
|
|
|
|
|
|
|
|
|
|
* sqlx - StructScan
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
func (r *Rows) StructScan(dest interface{}) error
|
|
|
|
|
|
|
|
|
|
func (r *Row) StructScan(dest interface{}) error
|
|
|
|
|
|
|
|
|
|
func StructScan(rows rowsi, dest interface{}) error
|
|
|
|
|
|
|
|
|
|
type rowsi interface {
|
|
|
|
|
Close() error
|
|
|
|
|
Columns() ([]string, error)
|
|
|
|
|
Err() error
|
|
|
|
|
Next() bool
|
|
|
|
|
Scan(...interface{}) error
|
|
|
|
|
}
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* sqlx - StructScan на практике
|
|
|
|
|
|
2020-04-09 11:15:34 +00:00
|
|
|
|
.code sqlx/structscan.go /^func Example/,/^}/
|
|
|
|
|
|
|
|
|
|
* sqlx - именованые аргументы
|
|
|
|
|
|
|
|
|
|
- работают для любого драйвера
|
|
|
|
|
- тоже защищают от SQL-injection
|
|
|
|
|
|
|
|
|
|
.code sqlx/named.go /^func Insert/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
* golang.yandex/hasql
|
|
|
|
|
|
|
|
|
|
- удобная работа с многохостовыми кластерами
|
|
|
|
|
- поддерживает database/sql и sqlx
|
|
|
|
|
|
|
|
|
|
* hasql - подключение и использование
|
|
|
|
|
|
|
|
|
|
.code hasql/open.go /^func Open/,/^}/
|
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
* Нетипичные драйверы
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
* Нетипичные драйверы - github.com/DATA-DOG/go-sqlmock
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 17:25:56 +00:00
|
|
|
|
.play -edit sqlmock/sqlmock_test.go /^func TestSelect/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
* Нетипичные драйверы - github.com/ClickHouse/clickhouse-go
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
.code clickhouse/clickhouse.go /^func Example/,/^}/
|
|
|
|
|
|
|
|
|
|
* Не-SQL драйверы - Redis
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
.code redis/redis.go /^func Example/,/^}/
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
* ORM
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
2020-04-09 13:00:41 +00:00
|
|
|
|
- github.com/jinzhu/gorm
|
|
|
|
|
- github.com/go-pg/pg
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
* Популярные базы данных и их драйверы
|
|
|
|
|
|
|
|
|
|
Совместимые с database/sql:
|
|
|
|
|
|
|
|
|
|
.link https://github.com/jackc/pgx - PostgreSQL
|
|
|
|
|
.link https://github.com/go-sql-driver/mysql - MySQL
|
|
|
|
|
.link https://github.com/ClickHouse/clickhouse-go - ClickHouse
|
|
|
|
|
|
2021-04-08 11:32:08 +00:00
|
|
|
|
Другие:
|
2020-04-08 19:20:23 +00:00
|
|
|
|
|
|
|
|
|
.link https://github.com/go-redis/redis - Redis
|
|
|
|
|
.link https://github.com/mongodb/mongo-go-driver - MongoDB
|