import"trpc.group/trpc-go/trpc-agent-go/session/mysql"// Minimal configurationsessionService,err:=mysql.NewService(mysql.WithMySQLClientDSN("user:password@tcp(localhost:3306)/db?charset=utf8mb4&parseTime=True&loc=Local"),)// Full production configurationsessionService,err:=mysql.NewService(mysql.WithMySQLClientDSN("user:password@tcp(localhost:3306)/db?charset=utf8mb4&parseTime=True&loc=Local"),mysql.WithSessionEventLimit(1000),mysql.WithSessionTTL(30*time.Minute),mysql.WithAppStateTTL(24*time.Hour),mysql.WithUserStateTTL(7*24*time.Hour),mysql.WithCleanupInterval(10*time.Minute),mysql.WithSoftDelete(true),mysql.WithAsyncPersisterNum(4),)
If your database was created with an older version, follow these migration steps.
Affected versions: Before v1.2.0
Fixed in: v1.2.0 and later
Background: Early versions of the session_summaries table had index design issues:
The initial version used a unique index that included the deleted_at column, but in MySQL NULL != NULL, so multiple records with deleted_at = NULL would not trigger the unique constraint
A later version changed to a regular lookup index (non-unique), which also could not prevent duplicate data
Both cases could lead to duplicate data.
Old indexes (one of the following):
idx_*_session_summaries_unique_active(app_name, user_id, session_id, filter_key, deleted_at) — unique index including deleted_at
idx_*_session_summaries_lookup(app_name, user_id, session_id, deleted_at) — regular index
New index: idx_*_session_summaries_unique_active(app_name(191), user_id(191), session_id(191), filter_key(191)) — unique index without deleted_at (uses prefix index to avoid Error 1071)
-- ============================================================================-- Migration script: Fix session_summaries unique index issue-- Back up your data before executing!-- ============================================================================-- Step 1: Check current indexesSHOWINDEXFROMsession_summaries;-- Step 2: Clean up duplicate data (keep newest record)DELETEt1FROMsession_summariest1INNERJOINsession_summariest2WHEREt1.app_name=t2.app_nameANDt1.user_id=t2.user_idANDt1.session_id=t2.session_idANDt1.filter_key=t2.filter_keyANDt1.deleted_atISNULLANDt2.deleted_atISNULLANDt1.id<t2.id;-- Step 3: Hard delete soft-deleted records (summary data is regenerable)DELETEFROMsession_summariesWHEREdeleted_atISNOTNULL;-- Step 4: Drop old index (choose based on Step 1 results)DROPINDEXidx_session_summaries_lookupONsession_summaries;-- Or if it's the old unique_active index (with deleted_at):-- DROP INDEX idx_session_summaries_unique_active ON session_summaries;-- Step 5: Create new unique index (without deleted_at)CREATEUNIQUEINDEXidx_session_summaries_unique_activeONsession_summaries(app_name(191),user_id(191),session_id(191),filter_key(191));-- Step 6: Verify migrationSELECTCOUNT(*)asduplicate_countFROM(SELECTapp_name,user_id,session_id,filter_key,COUNT(*)ascntFROMsession_summariesWHEREdeleted_atISNULLGROUPBYapp_name,user_id,session_id,filter_keyHAVINGcnt>1)t;-- Expected: duplicate_count = 0-- Step 7: Verify index creationSHOWINDEXFROMsession_summariesWHEREKey_name='idx_session_summaries_unique_active';
Notes:
If you configured WithTablePrefix("trpc_"), table and index names will have the prefix:
Table: trpc_session_summaries
Old index: idx_trpc_session_summaries_lookup or idx_trpc_session_summaries_unique_active
New index: idx_trpc_session_summaries_unique_active
Adjust the SQL above according to your actual configuration.
The new index does not include deleted_at, meaning soft-deleted summary records will block new records with the same business key. Since summary data is regenerable, it is recommended to hard delete soft-deleted records during migration (Step 3).
Use Cases
Scenario
Recommended Configuration
Production
Configure TTL, enable soft delete
Multi-app shared database
Use table prefix
Data recovery needed
Enable soft delete
Compliance audit
Enable soft delete + long TTL
Notes
Connection: Ensure MySQL service is accessible; use connection pooling
Character set: Use utf8mb4 for full Unicode support (including emoji)
Index optimization: The service automatically creates necessary indexes; use WithSkipDBInit(true) to skip auto table creation
Soft delete: Enabled by default; queries automatically filter deleted records
MySQL version: Requires MySQL 5.6.5+ for multiple TIMESTAMP columns with CURRENT_TIMESTAMP
Unique constraint: MySQL's UNIQUE constraint does not prevent multiple NULL values; the application layer handles active record uniqueness