Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
QLDBDriver Amazon untuk Go - Referensi buku masak
penting
Pemberitahuan akhir dukungan: Pelanggan yang ada akan dapat menggunakan Amazon QLDB hingga akhir dukungan pada 07/31/2025. Untuk detail selengkapnya, lihat Memigrasi QLDB Buku Besar Amazon ke Amazon Aurora Postgre
Panduan referensi ini menunjukkan kasus penggunaan umum QLDB driver Amazon untuk Go. Ini memberikan contoh kode Go yang menunjukkan cara menggunakan driver untuk menjalankan operasi create, read, update, dan delete (CRUD) dasar. Ini juga mencakup contoh kode untuk memproses data Amazon Ion. Selain itu, panduan ini menyoroti praktik terbaik untuk membuat transaksi idempoten dan menerapkan kendala keunikan.
catatan
Jika berlaku, beberapa kasus penggunaan memiliki contoh kode yang berbeda untuk setiap versi utama QLDB driver yang didukung untuk Go.
Mengimpor driver
Contoh kode berikut mengimpor driver dan AWS paket lain yang diperlukan.
catatan
Contoh ini juga mengimpor paket Amazon Ion (amzn/ion-go/ion
). Anda memerlukan paket ini untuk memproses data Ion saat menjalankan beberapa operasi data dalam referensi ini. Untuk mempelajari selengkapnya, lihat Bekerja dengan Amazon Ion.
Membuat instantiasi pengemudi
Contoh kode berikut membuat instance dari driver yang menghubungkan ke nama buku besar tertentu dalam tertentu Wilayah AWS.
Operasi CRUD
QLDBmenjalankan operasi create, read, update, dan delete (CRUD) sebagai bagian dari transaksi.
Awas
Sebagai praktik terbaik, buat transaksi tulis Anda benar-benar idempoten.
Membuat transaksi idempoten
Kami menyarankan Anda membuat transaksi tulis idempoten untuk menghindari efek samping yang tidak terduga dalam kasus percobaan ulang. Transaksi adalah idempoten jika dapat berjalan beberapa kali dan menghasilkan hasil yang identik setiap kali.
Misalnya, pertimbangkan transaksi yang menyisipkan dokumen ke dalam tabel bernamaPerson
. Transaksi harus terlebih dahulu memeriksa apakah dokumen sudah ada dalam tabel atau tidak. Tanpa pemeriksaan ini, tabel mungkin berakhir dengan dokumen duplikat.
Misalkan QLDB berhasil melakukan transaksi di sisi server, tetapi klien kehabisan waktu sambil menunggu respons. Jika transaksi tidak idempoten, dokumen yang sama dapat dimasukkan lebih dari sekali dalam kasus percobaan ulang.
Menggunakan indeks untuk menghindari pemindaian tabel penuh
Kami juga menyarankan Anda menjalankan pernyataan dengan klausa WHERE
predikat menggunakan operator kesetaraan pada bidang yang diindeks atau ID dokumen; misalnya, atau. WHERE indexedField = 123
WHERE indexedField IN (456, 789)
Tanpa pencarian yang diindeks ini, QLDB perlu melakukan pemindaian tabel, yang dapat menyebabkan batas waktu transaksi atau konflik kontrol konkurensi () yang optimis. OCC
Untuk informasi selengkapnya tentang OCC, lihat Model QLDB konkurensi Amazon.
Transaksi yang dibuat secara implisit
Fungsi QLDBDriver.ExecuteTransaction
membungkus transaksi yang dibuat secara implisit.
Anda dapat menjalankan pernyataan dalam fungsi lambda dengan menggunakan Transaction.Execute
fungsi. Pengemudi secara implisit melakukan transaksi saat fungsi lambda kembali.
Bagian berikut menunjukkan cara menjalankan CRUD operasi dasar, menentukan logika coba ulang kustom, dan menerapkan kendala keunikan.
Daftar Isi
Membuat tabel
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("CREATE TABLE Person") })
Membuat indeks
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("CREATE INDEX ON Person(GovId)") })
Membaca dokumen
var decodedResult map[string]interface{} // Assumes that Person table has documents as follows: // { "GovId": "TOYENC486FH", "FirstName": "Brent" } _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT * FROM Person WHERE GovId = 'TOYENC486FH'") if err != nil { return nil, err } for result.Next(txn) { ionBinary := result.GetCurrentData() err = ion.Unmarshal(ionBinary, &decodedResult) if err != nil { return nil, err } fmt.Println(decodedResult) // prints map[GovId: TOYENC486FH FirstName:Brent] } if result.Err() != nil { return nil, result.Err() } return nil, nil }) if err != nil { panic(err) }
Menggunakan parameter kueri
Contoh kode berikut menggunakan parameter query tipe asli.
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("SELECT * FROM Person WHERE GovId = ?", "TOYENC486FH") }) if err != nil { panic(err) }
Contoh kode berikut menggunakan beberapa parameter query.
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("SELECT * FROM Person WHERE GovId = ? AND FirstName = ?", "TOYENC486FH", "Brent") }) if err != nil { panic(err) }
Contoh kode berikut menggunakan daftar parameter query.
govIDs := []string{}{"TOYENC486FH", "ROEE1", "YH844"} result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("SELECT * FROM Person WHERE GovId IN (?,?,?)", govIDs...) }) if err != nil { panic(err) }
catatan
Saat Anda menjalankan kueri tanpa pencarian yang diindeks, itu akan memanggil pemindaian tabel lengkap. Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId
lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId
, kueri dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.
Menyisipkan dokumen
Contoh kode berikut menyisipkan tipe data asli.
_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { // Check if a document with a GovId of TOYENC486FH exists // This is critical to make this transaction idempotent result, err := txn.Execute("SELECT * FROM Person WHERE GovId = ?", "TOYENC486FH") if err != nil { return nil, err } // Check if there are any results if result.Next(txn) { // Document already exists, no need to insert } else { person := map[string]interface{}{ "GovId": "TOYENC486FH", "FirstName": "Brent", } _, err = txn.Execute("INSERT INTO Person ?", person) if err != nil { return nil, err } } return nil, nil })
Transaksi ini menyisipkan dokumen ke dalam Person
tabel. Sebelum memasukkan, pertama-tama memeriksa apakah dokumen sudah ada di tabel. Pemeriksaan ini membuat transaksi idempoten di alam. Bahkan jika Anda menjalankan transaksi ini beberapa kali, itu tidak akan menyebabkan efek samping yang tidak diinginkan.
catatan
Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId
lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId
, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.
Menyisipkan beberapa dokumen dalam satu pernyataan
Untuk menyisipkan beberapa dokumen dengan menggunakan satu INSERT pernyataan, Anda dapat meneruskan parameter daftar tipe ke pernyataan sebagai berikut.
// people is a list txn.Execute("INSERT INTO People ?", people)
Anda tidak melampirkan variabel placeholder (?
) dalam tanda kurung sudut ganda (<<...>>
) saat melewati daftar. Dalam pernyataan PartiQL manual, tanda kurung sudut ganda menunjukkan koleksi tidak berurutan yang dikenal sebagai tas.
Memperbarui dokumen
Contoh kode berikut menggunakan tipe data asli.
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("UPDATE Person SET FirstName = ? WHERE GovId = ?", "John", "TOYENC486FH") })
catatan
Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId
lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId
, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.
Menghapus dokumen
Contoh kode berikut menggunakan tipe data asli.
result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("DELETE FROM Person WHERE GovId = ?", "TOYENC486FH") })
catatan
Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId
lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId
, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.
Menjalankan beberapa pernyataan dalam transaksi
// This code snippet is intentionally trivial. In reality you wouldn't do this because you'd // set your UPDATE to filter on vin and insured, and check if you updated something or not. func InsureCar(driver *qldbdriver.QLDBDriver, vin string) (bool, error) { insured, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute( "SELECT insured FROM Vehicles WHERE vin = ? AND insured = FALSE", vin) if err != nil { return false, err } hasNext := result.Next(txn) if !hasNext && result.Err() != nil { return false, result.Err() } if hasNext { _, err = txn.Execute( "UPDATE Vehicles SET insured = TRUE WHERE vin = ?", vin) if err != nil { return false, err } return true, nil } return false, nil }) if err != nil { panic(err) } return insured.(bool), err }
Logika coba lagi
Execute
Fungsi pengemudi memiliki mekanisme coba ulang bawaan yang mencoba ulang transaksi jika terjadi pengecualian yang dapat dicoba ulang (seperti batas waktu atau konflik). OCC Jumlah maksimum upaya coba lagi dan strategi backoff dapat dikonfigurasi.
Batas coba lagi default adalah4
, dan strategi backoff default adalah ExponentialBackoffStrategy10
Anda dapat mengatur kebijakan coba lagi per instance driver dan juga per transaksi dengan menggunakan instance. RetryPolicy
Contoh kode berikut menentukan logika coba lagi dengan batas coba ulang khusus dan strategi backoff khusus untuk instance driver.
import ( "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/qldbsession" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) func main() { awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("
us-east-1
"))) qldbSession := qldbsession.New(awsSession) // Configuring retry limit to 2 retryPolicy := qldbdriver.RetryPolicy{MaxRetryLimit: 2} driver, err := qldbdriver.New("test-ledger", qldbSession, func(options *qldbdriver.DriverOptions) { options.RetryPolicy = retryPolicy }) if err != nil { panic(err) } // Configuring an exponential backoff strategy with base of 20 milliseconds retryPolicy = qldbdriver.RetryPolicy{ MaxRetryLimit: 2, Backoff: qldbdriver.ExponentialBackoffStrategy{SleepBase: 20, SleepCap: 4000, }} driver, err = qldbdriver.New("test-ledger", qldbSession, func(options *qldbdriver.DriverOptions) { options.RetryPolicy = retryPolicy }) if err != nil { panic(err) } }
Contoh kode berikut menentukan logika coba lagi dengan batas coba ulang kustom dan strategi backoff khusus untuk fungsi anonim tertentu. SetRetryPolicy
Fungsi ini mengesampingkan kebijakan coba lagi yang disetel untuk instance driver.
import ( "context" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/qldbsession" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) func main() { awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("
us-east-1
"))) qldbSession := qldbsession.New(awsSession) // Configuring retry limit to 2 retryPolicy1 := qldbdriver.RetryPolicy{MaxRetryLimit: 2} driver, err := qldbdriver.New("test-ledger", qldbSession, func(options *qldbdriver.DriverOptions) { options.RetryPolicy = retryPolicy1 }) if err != nil { panic(err) } // Configuring an exponential backoff strategy with base of 20 milliseconds retryPolicy2 := qldbdriver.RetryPolicy{ MaxRetryLimit: 2, Backoff: qldbdriver.ExponentialBackoffStrategy{SleepBase: 20, SleepCap: 4000, }} // Overrides the retry policy set by the driver instance driver.SetRetryPolicy(retryPolicy2) driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("CREATE TABLE Person") }) }
Menerapkan kendala keunikan
QLDBtidak mendukung indeks unik, tetapi Anda dapat menerapkan perilaku ini di aplikasi Anda.
Misalkan Anda ingin menerapkan kendala keunikan pada GovId
bidang dalam tabel. Person
Untuk melakukan ini, Anda dapat menulis transaksi yang melakukan hal berikut:
-
Tegaskan bahwa tabel tidak memiliki dokumen yang ada dengan yang ditentukan
GovId
. -
Masukkan dokumen jika pernyataan lolos.
Jika transaksi yang bersaing secara bersamaan melewati pernyataan, hanya satu transaksi yang akan berhasil dilakukan. Transaksi lainnya akan gagal dengan pengecualian OCC konflik.
Contoh kode berikut menunjukkan bagaimana menerapkan logika kendala keunikan ini.
govID := "TOYENC486FH" document := map[string]interface{}{ "GovId": "TOYENC486FH", "FirstName": "Brent", } result, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { // Check if doc with GovId = govID exists result, err := txn.Execute("SELECT * FROM Person WHERE GovId = ?", govID) if err != nil { return nil, err } // Check if there are any results if result.Next(txn) { // Document already exists, no need to insert return nil, nil } return txn.Execute("INSERT INTO Person ?", document) }) if err != nil { panic(err) }
catatan
Dalam contoh ini, kami merekomendasikan memiliki indeks di GovId
lapangan untuk mengoptimalkan kinerja. Tanpa indeks aktifGovId
, pernyataan dapat memiliki lebih banyak latensi dan juga dapat menyebabkan pengecualian OCC konflik atau batas waktu transaksi.
Bekerja dengan Amazon Ion
Bagian berikut menunjukkan cara menggunakan modul Amazon Ion untuk memproses data Ion.
Mengimpor modul Ion
import "github.com/amzn/ion-go/ion"
Membuat tipe Ion
Pustaka Ion untuk Go saat ini tidak mendukung Document Object Model (DOM), sehingga Anda tidak dapat membuat tipe data Ion. Tetapi Anda dapat membuat marshal dan unmarshal antara tipe asli Go dan biner Ion saat bekerja dengannya. QLDB
Mendapatkan biner Ion
aDict := map[string]interface{}{ "GovId": "TOYENC486FH", "FirstName": "Brent", } ionBytes, err := ion.MarshalBinary(aDict) if err != nil { panic(err) } fmt.Println(ionBytes) // prints [224 1 0 234 238 151 129 131 222 147 135 190 144 133 71 111 118 73 100 137 70 105 114 115 116 78 97 109 101 222 148 138 139 84 79 89 69 78 67 52 56 54 70 72 139 133 66 114 101 110 116]
Mendapatkan teks Ion
aDict := map[string]interface{}{ "GovId": "TOYENC486FH", "FirstName": "Brent", } ionBytes, err := ion.MarshalText(aDict) if err != nil { panic(err) } fmt.Println(string(ionBytes)) // prints {FirstName:"Brent",GovId:"TOYENC486FH"}
Untuk informasi selengkapnya tentang Ion, lihat dokumentasi Amazon Ion