---
id: 134c150de56c188c925476664026a1ff
author: Lemon Mint
title: 'gosuda.org/sqlite3: CGO_ENABLED=0 database/sql illesztőprogram megosztott memórián alapuló IPC felett'
description: Go-hoz készült, database/sql-kompatibilis SQLite 3.54.1 illesztőprogram, amely CGO_ENABLED=0 mellett működik, HQQ osztott memóriás munkafolyamat-izolációt, 64 KiB-os kötegelt sorelőtöltést és SLSA-igazolt bináris fájlokat biztosít.
language: hu
date: 2026-10-18T14:02:16.803040007Z
path: /sqlite3
go_package: gosuda.org/sqlite3
go_repourl: https://github.com/gosuda/hqq-sqlite3.git
category: database
---

`gosuda.org/sqlite3` egy `CGO_ENABLED=0` `database/sql` illesztőprogram Go-hoz, amely a hivatalos C SQLite `3.54.1` amalgamációt egy elszigetelt munkafolyamatban futtatja, [HQQ](https://gosuda.org/hqq) megosztott memóriás gyűrűpuffereken keresztül. A `"sqlite3"` illesztőprogram-névvel regisztrálódik, támogatja a `github.com/mattn/go-sqlite3` DSN lekérdezési paramétereit, hat operációs rendszer- és architektúra-célplatformhoz SLSA-attesztált, előre fordított szerverbináris fájlokat ágyaz be, és kérésenkénti csővezetékelést (request pipelining) valamint 64 KiB-os kötegelt előtöltést (batch prefetching) alkalmaz, így többsoros lekérdezéseken felülmúlja a folyamaton belüli `cgo` megoldást.

```bash
go get gosuda.org/sqlite3@v0.3.3540100
```

## Miért még egy Go SQLite illesztőprogram?

Az SQLite a világ egyik legszélesebb körben telepített szoftverkomponense, mégis Go-ból történő használata hagyományosan kényelmetlen választás elé állította a mérnököket: vagy az egyszerű build folyamat vagy a motor hűsége mellett kellett dönteniük.

Az egyik oldalon a `github.com/mattn/go-sqlite3` áll, a régóta használt közösségi szabvány. Ez `cgo`-n keresztül közvetlenül becsomagolja a hivatalos C SQLite amalgamációt. Így a valódi C lekérdezésoptimalizálót, a teljes WAL-párhuzamossági szemantikát és a kiszámítható C memóriakezelést kapjuk. Az ár a `CGO_ENABLED=1`: a helyi buildek és a CI-folyamatok lelassulnak, a minimális scratch vagy distroless konténerképeknek megfelelő C futtatókönyvtárakra van szükségük, egy másik operációs rendszerre vagy CPU-architektúrára történő keresztfordításhoz teljes C keresztfordító-eszköztárra van szükség, és a C-ben bekövetkező bármely memóriasérülés ugyanazt a Go-folyamat címtartományát érinti.

A másik oldalon a tiszta Go SQLite portok állnak, amelyeket a C amalgamáció emulált C futtatókörnyezeten (`libc`) keresztül, mechanikus fordítással alakítottak Go forráskóddá. Ezek visszaállítják a `CGO_ENABLED=0` lehetőségét, ami triviálissá teszi a buildelést. Tartós terhelés mellett azonban a lefordított C-heap és a soronkénti Go-allokációk növelik a szemétgyűjtési nyomást, a zárolás, a foglaltsági időkorlátok vagy az utasítások megszakítása során felmerülő finom szélsőséges esetek pedig eltérhetnek a natív C buildektől.

A `gosuda.org/sqlite3` azért készült, hogy a Go alkalmazásoknak ne kelljen választaniuk a `CGO_ENABLED=0` és a valódi C SQLite motor között. A hivatalos SQLite `3.54.1` C amalgamáció egy dedikált, megosztott memóriás szerverbe (`hqq-sqlite-server`) fordításával, valamint a `gosuda.org/hqq` csomagon keresztüli kommunikációval a Go bináris fájl `CGO_ENABLED=0` módban fordul, miközben a módosítatlan, `-O3` optimalizált C SQLite egy folyamathatáron átívelve fut.

## Konfiguráció nélküli futtatás: a `go get`-től a `sql.Open`-ig

A `github.com/mattn/go-sqlite3` cseréje egy meglévő Go kódbázisban csupán a vak importútvonal megváltoztatását igényli. Az illesztőprogram `"sqlite3"` néven (és explicit kiválasztáshoz `"hqq-sqlite"` néven) regisztrálódik, és ugyanazokat a DSN lekérdezési karakterláncokat fogadja el:

```go
package main

import (
	"context"
	"database/sql"
	"fmt"
	"log"

	_ "gosuda.org/sqlite3"
)

func main() {
	dsn := "file:app.db?_journal_mode=WAL&_busy_timeout=5000&_txlock=immediate&_foreign_keys=on"
	db, err := sql.Open("sqlite3", dsn)
	if err != nil {
		log.Fatal(err)
	}
	defer db.Close()

	ctx := context.Background()
	if _, err := db.ExecContext(ctx, `CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT NOT NULL)`); err != nil {
		log.Fatal(err)
	}
	if _, err := db.ExecContext(ctx, `INSERT INTO users (name) VALUES (?)`, "Ada Lovelace"); err != nil {
		log.Fatal(err)
	}

	var id int64
	var name string
	if err := db.QueryRowContext(ctx, `SELECT id, name FROM users WHERE name = ?`, "Ada Lovelace").Scan(&id, &name); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("user #%d: %s\n", id, name)
}
```

### Beágyazott SLSA-attesztált munkafolyamat-binárisok

Egy természetes kérdés, amely akkor merül fel, amikor megtudjuk, hogy egy könyvtár C munkafolyamatot használ: _„Külön C binárist kell telepítenem vagy szállítanom a Go programommal együtt?”_

Nem. A `gosuda.org/sqlite3` mind a hat fő célplatformhoz előre fordított `hqq-sqlite-server` binárisokat ágyaz be közvetlenül a platformcímkézett Go fájlokba (`internal/embedded/embed_<goos>_<goarch>.go`). Mivel a Go build-megszorítások csak a céljának megfelelő `GOOS` és `GOARCH` fájlt fordítják le, a `GOOS=linux GOARCH=arm64 go build` parancs kizárólag a körülbelül 1,4 MiB-os `linux/arm64` szerverbinárist ágyazza be.

| Céloperációs rendszer | Célarchitektúra (`GOARCH`) | Beágyazott bináris                    | Build-eszköztár és eredet                         |
| :--------------------- | :------------------------- | :------------------------------------ | :------------------------------------------------ |
| **Linux**              | `amd64`, `arm64`           | `hqq-sqlite-server_linux_<arch>`      | GCC `-O3`, SLSA Build L3 eredetiség               |
| **macOS**              | `arm64`, `amd64`           | `hqq-sqlite-server_darwin_<arch>`     | AppleClang `-O3`, SLSA Build L3 eredetiség        |
| **Windows**            | `amd64`                    | `hqq-sqlite-server_windows_amd64.exe` | MSVC `-O2`, SLSA Build L3 eredetiség              |
| **Windows**            | `arm64`                    | `hqq-sqlite-server_windows_arm64.exe` | `zig cc -target aarch64-windows-gnu -O3`, SLSA L3 |

Amikor a `sql.Open` létrehozza az első kapcsolatot, az `autolaunch.go` a beágyazott binárist a felhasználói gyorsítótár könyvtárába (`$XDG_CACHE_HOME/hqq/bin/<sha256>/`) írja ki, ellenőrzi kriptográfiai SHA-256 üzenetkivonatát a `hashes.go` fájlban rögzített `ReleaseHashes` térképhez képest a `gosuda.org/hqq/secureexec` csomagon keresztül, majd a munkafolyamatot a `--parent-stdin` kapcsolóval indítja el, így az élettartama szigorúan a Go folyamatához kötött.

### `mattn/go-sqlite3` DSN-kompatibilitás tiszta lapról

Ahhoz, hogy valódi közvetlen csereként működjön, a DSN-elemző (`dsn.go`) a `mattn/go-sqlite3` kódbázisokban használt kapcsolat- és pragma-beállítások tiszta lapról írt másolatát valósítja meg:

| DSN lekérdezési paraméter                                                                     | Elfogadott értékek                                      | SQLite hatás                                                                                         |
| :-------------------------------------------------------------------------------------------- | :------------------------------------------------------ | :--------------------------------------------------------------------------------------------------- |
| `_busy_timeout` / `_timeout`                                                                  | Egész számú milliszekundum (pl. `5000`)                 | Munkamenet-megnyitáskor meghívja a `sqlite3_busy_timeout(db, ms)` függvényt.                        |
| `_journal_mode` / `_journal`                                                                  | `DELETE`, `TRUNCATE`, `PERSIST`, `MEMORY`, `WAL`, `OFF` | Végrehajtja a `PRAGMA journal_mode = <mode>` utasítást.                                              |
| `_txlock`                                                                                     | `immediate`, `exclusive`, `deferred`                    | A `db.BeginTx` számára a `BEGIN IMMEDIATE`, `BEGIN EXCLUSIVE` vagy `BEGIN DEFERRED` utasítást választja ki. |
| `_foreign_keys` / `_fk`                                                                       | `on`, `true`, `1`, `off`, `false`, `0`                  | Végrehajtja a `PRAGMA foreign_keys = ON/OFF` utasítást.                                              |
| `_synchronous` / `_sync`                                                                      | `0`/`OFF`, `1`/`NORMAL`, `2`/`FULL`, `3`/`EXTRA`        | Végrehajtja a `PRAGMA synchronous = <level>` utasítást.                                              |
| `_cache_size`                                                                                 | Egész számú lapok vagy `-KiB` (pl. `-20000`)            | Végrehajtja a `PRAGMA cache_size = <val>` utasítást.                                                 |
| `_loc`                                                                                        | `auto` vagy IANA-időzóna (pl. `UTC`, `Asia/Seoul`)      | A `DATETIME`/`TIMESTAMP` szöveges oszlopokat a céltartománybeli `*time.Time` típusba alakítja.       |
| `mode`                                                                                        | `ro`, `rw`, `rwc`, `memory`                             | Beállítja a `SQLITE_OPEN_READONLY`, `SQLITE_OPEN_READWRITE`, `SQLITE_OPEN_CREATE` vagy `SQLITE_OPEN_MEMORY` értékét. |
| `_case_sensitive_like`, `_query_only`, `_recursive_triggers`, `_secure_delete`, `_AutoVacuum` | Logikai értékek vagy módegészek                         | A megfelelő munkamenet-`PRAGMA` alkalmazása a kapcsolat inicializálásakor.                          |

## A folyamatizoláció átviteli sebességi előnnyé alakítása

Első pillantásra úgy tűnhet, hogy az SQLite külön folyamatban történő futtatása lassabb kell hogy legyen, mint a `sqlite3_step` folyamaton belüli hívása `cgo`-n keresztül. A gyakorlatban éppen az ellenkezője történik, amint a lekérdezés egynél több sort ad vissza.

### A soronkénti `cgo` hívások rejtett költsége

Egy hagyományos `cgo` SQLite illesztőprogramban a `database/sql` egyszerre egy sort és egy oszlopot bejárva iterál. 4 oszlopot tartalmazó 1000 sor olvasása a következőket váltja ki:

- 1000 `cgo` hívás a `sqlite3_step` függvényhez
- 4000 `cgo` hívás a `sqlite3_column_type` és a `sqlite3_column_int64` / `sqlite3_column_text` függvényekhez
- Több ezer egyedi határátlépés a Go ütemező és a C verem között

### Kérés-csővezetékelés és 64 KiB-os kötegelt előtöltés

A `gosuda.org/sqlite3` a soronkénti határátlépéseket úgy szünteti meg, hogy a vezetéki protokollt két mechanizmus köré tervezi át, amelyek a `stmt.go`, `rows.go` és `sqlite3/server/sqlite3_hooks.c` fájlokban találhatók:

```text
Go kliens (stmt.go / rows.go)                       C11 munkafolyamat (sqlite3_hooks.c)
-----------------------------                       ----------------------------
1. Csővezeték egy repülésben:
   ResetAsync + BindValuesAsync
   + StmtInfoAsync + FetchRowsAsync(128)  =======>  reset -> bind -> stmt_info ->
                                                    ciklus sqlite3_step() legfeljebb 128 sorig
                                          <=======  1. köteg (1..128. sor 64 KiB-os résben)
2. Azonnal indítsa az előtöltést:
   FetchRowsAsync(128) (2. köteg)         =======>  ciklus sqlite3_step() a 129..256. sorokra
   Miközben a C a 2. köteget lépteti,
   a Go hívó az 1. köteg 1..128. sorait
   olvassa be!                            <=======  2. köteg kész a megosztott memóriában
```

1. **Egyfordulós lekérdezés-csővezetékelés (`stmt.go`)**: Amikor a `QueryContext` vagy a `Stmt.QueryContext` egy csak olvasható utasítást futtat, az `s.query()` a `reset`, a `bind_values`, a `stmt_info` (első végrehajtáskor) és a `fetch_rows` műveleteket aszinkron módon, egyetlen megosztott memóriás fordulóban küldi el. Mind a négy művelet egymás után fut le a C munkafolyamaton, és egyetlen körutazással tér vissza.
2. **Szoros C kötegelési ciklusok és aszinkron előtöltés (`rows.go`)**: A `fetch_rows` (`sqlite3_hooks.c`) belsejében a C munkafolyamat natív C ciklusban lépteti a `sqlite3_step(stmt)` függvényt, és legfeljebb `FetchSize` (alapértelmezés szerint 128) sort kódol közvetlenül a 64 KiB-os megosztott memóriás válaszrésbe, amíg el nem éri a kötegkorlátot, a rés meg nem telik, vagy be nem következik a `SQLITE_DONE`. Amint a `rows.ingest()` dekódolja az 1. köteget, még mielőtt az első sort visszaadná a hívónak, elindítja a `FetchRowsAsync` hívást a 2. kötegre. Miközben a Go kódja az 1. köteget olvassa, a C munkafolyamat már egy másik CPU-magon lépteti a 2. köteget.

Apple M4 (`darwin/arm64`) processzoron, ugyanazon SQLite adatbázison összehasonlítva a `gosuda.org/sqlite3` (`CGO_ENABLED=0`) és a `github.com/mattn/go-sqlite3` (`CGO_ENABLED=1`) illesztőprogramokat, a kötegelés és a csővezetékelés hatása látszik:

| Terhelés                            | `gosuda.org/sqlite3` (`CGO_ENABLED=0`) | `mattn/go-sqlite3` (`CGO_ENABLED=1`) | Relatív sebesség                     |
| :---------------------------------- | -------------------------------------: | -----------------------------------: | :----------------------------------- |
| **Pontlekérdezés (`QueryRow` PK szerint)** |            `3,52 µs/op` (9 B, 1 allokáció) |       `3,56 µs/op` (232 B, 11 allokáció) | **1,01x (paritás, 11x kevesebb allokáció)** |
| **100 soros bejárás (`rows.Next`)**      |    `20,41 µs/op` (30,5 KB, 211 allokáció) |   `36,34 µs/op` (21,8 KB, 309 allokáció) | **1,78x gyorsabb**                     |
| **1000 soros bejárás (`rows.Next`)**    |  `125,92 µs/op` (296 KB, 2030 allokáció) | `349,10 µs/op` (216 KB, 3009 allokáció) | **2,77x gyorsabb**                     |
| **Előkészített beszúrás (automatikus commit)**    |           `5,33 µs/op` (0 B, 0 allokáció) |        `5,88 µs/op` (120 B, 5 allokáció) | **1,10x gyorsabb (0 allokáció)**          |
| **100 soros tranzakciós köteg**         |         `189,99 µs/op` (16 B, 1 allokáció) |  `191,50 µs/op` (12,1 KB, 503 allokáció) | **1,01x (500x kevesebb allokáció)**        |

## Megszakítás, útvonal-homokozózás és kapcsolatkészlet-helyreállítás

Az SQLite elszigetelt munkafolyamatban történő futtatása az illesztőprogram időtúllépés-kezelését, a nem megbízható SQL-kezelést és a fájlrendszer-határokat is erősíti:

- **Determinisztikus kontextus-megszakítás (`conn.go` és `errors.go`)**: Minden illesztőprogram-hívás egy könnyűsúlyú `context.AfterFunc` őrt (`cn.guard`) állít be. Ha a hívó `context.Context` megszakad, vagy a határideje lejár, miközben egy lassú rekurzív lekérdezés vagy zárvárakozás fut a szerveren, az őr rossznak jelöli a kapcsolatot, megszakítja a helyi munkamenet-kapcsolatot, és sávon kívüli `Cancel()` keretet küld. A C munkafolyamat azonnal meghívja a `sqlite3_interrupt(db)` függvényt, feloldva a `sqlite3_step` blokkolását, a Go illesztőprogram pedig a keletkező `SQLITE_INTERRUPT` állapotot `context.Canceled` vagy `context.DeadlineExceeded` értékre képezi le, és utasítja a `database/sql` csomagot, hogy cserélje le a kapcsolatot a készletben.
- **Könyvtár-homokozózás (`sqlsrv_pathrules.c`)**: A C munkafolyamat minden `open_v2` híváskor érvényesíti a `--allow-dir` útvonalszabályokat, feloldja a szimbolikus linkeket, és elutasítja a megengedett könyvtáron kívüli relatív `..` bejárást. A `sqlite3_load_extension` és a `SQLITE_LIMIT_ATTACHED` alapértelmezés szerint letiltott, így az SQL-injektálás nem léphet ki az adatbázis-könyvtárból, és nem tölthet be tetszőleges megosztott objektumokat.

## Tárolóelrendezés

A tárolót úgy strukturálták, hogy a legfelső szintű csomag biztosítsa a közvetlen `database/sql` illesztőprogramot, miközben a `launcher/` és a `sqlite3/` könyvtárak továbbra is elérhetők maradnak a haladó, egyéni szerveres telepítésekhez:

```text
gosuda.org/sqlite3
├── driver.go / api.go         # database/sql illesztőprogram-regisztráció ("sqlite3") és Connector API
├── dsn.go                     # Tiszta lapról írt mattn/go-sqlite3 DSN-elemző és pragma-konfiguráció
├── conn.go / tx.go            # Munkamenet-életciklus, kontextusőr és tranzakciós állapotgép
├── stmt.go / rows.go          # Egyfordulós kérés-csővezetékelés és 64 KiB-os kötegelt előtöltés
├── errors.go                  # Típusos SQLite elsődleges és kiterjesztett hibakódok, őrszem-illesztés
├── autolaunch.go / hashes.go  # Konfiguráció nélküli beágyazott szerver-kibontás és SHA-256 rögzítés
├── internal/embedded/         # Platformcímkézett //go:embed binárisok (linux, darwin, windows)
├── launcher/                  # Konfigurálható folyamatfelügyelő egyéni szerveres telepítésekhez
└── sqlite3/                   # Generált hqq-bindgen Go kliens és C11 SQLite szerverforrás
    └── server/                # C11 szerver-implementáció (sqlite3_hooks.c, sqlsrv_policy.c)
```

## Első lépések

Telepítse a modult a `go get` paranccsal, majd nyissa meg adatbázisát a `sql.Open("sqlite3", dsn)` hívással:

```bash
go get gosuda.org/sqlite3@v0.3.3540100
```

- **GitHub-tároló**: [https://github.com/gosuda/hqq-sqlite3](https://github.com/gosuda/hqq-sqlite3)
- **DSN- és pragma-referencia**: [docs/DSN.md](https://github.com/gosuda/hqq-sqlite3/blob/main/docs/DSN.md)
- **Architektúra és vezetékprotokoll**: [docs/ARCHITECTURE.md](https://github.com/gosuda/hqq-sqlite3/blob/main/docs/ARCHITECTURE.md)
