or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-operations.mdcursors.mdindex.mdmulti-database.mdtransactions.md

transactions.mddocs/

0

# Transaction Management

1

2

ACID transaction handling for consistent database operations. Transactions provide atomicity, consistency, isolation, and durability guarantees for all database modifications. LMDB supports concurrent readers with exclusive writers using MVCC (Multi-Version Concurrency Control).

3

4

## Capabilities

5

6

### Transaction Creation

7

8

Create read-only or read-write transactions with optional parent transaction support and buffer management.

9

10

```python { .api }

11

class Environment:

12

def begin(self, db=None, parent=None, write: bool = False,

13

buffers: bool = False) -> Transaction:

14

"""

15

Begin a new transaction.

16

17

Parameters:

18

- db: Default database handle for transaction operations

19

- parent: Parent transaction (for nested transactions)

20

- write: Enable write operations (default read-only)

21

- buffers: Return buffer objects instead of copying data

22

23

Returns:

24

Transaction instance

25

26

Note:

27

Write transactions are exclusive - only one write transaction per environment.

28

Read transactions are concurrent and don't block each other or writers.

29

"""

30

```

31

32

### Transaction Lifecycle

33

34

Commit or abort transactions with proper resource cleanup and error handling.

35

36

```python { .api }

37

class Transaction:

38

def commit(self) -> None:

39

"""

40

Commit all operations in transaction and close it.

41

Changes become visible to other transactions.

42

43

Raises:

44

Various errors if commit fails (disk full, corruption, etc.)

45

"""

46

47

def abort(self) -> None:

48

"""

49

Abandon all operations and close transaction.

50

All changes are discarded without affecting database.

51

Safe to call multiple times.

52

"""

53

54

def id(self) -> int:

55

"""

56

Get unique transaction identifier.

57

58

Returns:

59

Transaction ID (monotonically increasing)

60

"""

61

```

62

63

### Data Retrieval

64

65

Read operations for accessing stored data with flexible default handling and multi-database support.

66

67

```python { .api }

68

class Transaction:

69

def get(self, key: bytes, default=None, db=None) -> bytes:

70

"""

71

Retrieve value for given key.

72

73

Parameters:

74

- key: Key to lookup (bytes object)

75

- default: Value returned if key not found

76

- db: Database handle (uses transaction default if None)

77

78

Returns:

79

Value bytes or default if key not found

80

"""

81

```

82

83

### Data Modification

84

85

Write operations for storing, updating, and removing data with extensive control options.

86

87

```python { .api }

88

class Transaction:

89

def put(self, key: bytes, value: bytes, dupdata: bool = True,

90

overwrite: bool = True, append: bool = False, db=None) -> bool:

91

"""

92

Store key-value pair in database.

93

94

Parameters:

95

- key: Key bytes (must not be empty)

96

- value: Value bytes

97

- dupdata: Allow duplicate keys (ignored if database doesn't support duplicates)

98

- overwrite: Replace existing value (False raises KeyExistsError if key exists)

99

- append: Optimize for appending (key must be >= all existing keys)

100

- db: Database handle

101

102

Returns:

103

True if key was inserted, False if key existed and was updated

104

105

Raises:

106

KeyExistsError: If overwrite=False and key exists

107

MapFullError: If database is full

108

"""

109

110

def replace(self, key: bytes, value: bytes, db=None) -> bytes:

111

"""

112

Replace existing value and return old value.

113

114

Parameters:

115

- key: Key to replace

116

- value: New value

117

- db: Database handle

118

119

Returns:

120

Previous value

121

122

Raises:

123

NotFoundError: If key doesn't exist

124

"""

125

126

def pop(self, key: bytes, db=None) -> bytes:

127

"""

128

Get value and delete key in single operation.

129

130

Parameters:

131

- key: Key to retrieve and delete

132

- db: Database handle

133

134

Returns:

135

Value that was stored

136

137

Raises:

138

NotFoundError: If key doesn't exist

139

"""

140

141

def delete(self, key: bytes, value: bytes = b'', db=None) -> bool:

142

"""

143

Delete key-value pair from database.

144

145

Parameters:

146

- key: Key to delete

147

- value: Specific value to delete (for duplicate keys, empty for any value)

148

- db: Database handle

149

150

Returns:

151

True if key was found and deleted

152

153

Raises:

154

NotFoundError: If key doesn't exist (when value specified)

155

"""

156

```

157

158

### Database Operations

159

160

Transaction-scoped database management including statistics and database deletion.

161

162

```python { .api }

163

class Transaction:

164

def stat(self, db) -> dict:

165

"""

166

Get database statistics within transaction context.

167

168

Parameters:

169

- db: Database handle

170

171

Returns:

172

Dictionary with statistics:

173

- psize: Page size

174

- depth: B-tree depth

175

- branch_pages: Internal pages

176

- leaf_pages: Leaf pages

177

- overflow_pages: Overflow pages

178

- entries: Data items

179

"""

180

181

def drop(self, db, delete: bool = True) -> None:

182

"""

183

Empty or delete database.

184

185

Parameters:

186

- db: Database handle

187

- delete: If True, delete database; if False, empty database

188

189

Note:

190

Cannot delete the default database, only empty it

191

"""

192

```

193

194

### Cursor Creation

195

196

Create cursors for iteration and positioned access within transaction context.

197

198

```python { .api }

199

class Transaction:

200

def cursor(self, db=None) -> Cursor:

201

"""

202

Create cursor for iterating over database.

203

204

Parameters:

205

- db: Database handle (uses transaction default if None)

206

207

Returns:

208

Cursor instance bound to this transaction and database

209

"""

210

```

211

212

### Usage Examples

213

214

#### Basic Transaction Operations

215

216

```python

217

import lmdb

218

219

env = lmdb.open('/path/to/database')

220

221

# Write transaction with context manager (recommended)

222

with env.begin(write=True) as txn:

223

# Store data

224

txn.put(b'user:1', b'{"name": "Alice", "age": 30}')

225

txn.put(b'user:2', b'{"name": "Bob", "age": 25}')

226

227

# Update existing data

228

txn.put(b'user:1', b'{"name": "Alice Smith", "age": 31}')

229

230

# Conditional insert (fails if key exists)

231

try:

232

txn.put(b'user:3', b'{"name": "Charlie"}', overwrite=False)

233

except lmdb.KeyExistsError:

234

print("User 3 already exists")

235

236

# Get and delete in one operation

237

old_value = txn.pop(b'user:2')

238

print(f"Removed user: {old_value}")

239

240

# Transaction auto-commits when leaving context successfully

241

242

# Read transaction

243

with env.begin() as txn:

244

user1 = txn.get(b'user:1')

245

if user1:

246

print(f"User 1: {user1}")

247

248

# Safe get with default

249

user99 = txn.get(b'user:99', default=b'Not found')

250

print(f"User 99: {user99}")

251

252

env.close()

253

```

254

255

#### Manual Transaction Management

256

257

```python

258

import lmdb

259

260

env = lmdb.open('/path/to/database')

261

262

# Manual transaction management (not recommended - use context managers)

263

txn = env.begin(write=True)

264

try:

265

txn.put(b'key1', b'value1')

266

txn.put(b'key2', b'value2')

267

268

# Simulate error condition

269

if some_error_condition:

270

txn.abort() # Discard changes

271

print("Transaction aborted")

272

else:

273

txn.commit() # Save changes

274

print("Transaction committed")

275

276

except Exception as e:

277

txn.abort() # Always abort on exception

278

print(f"Transaction failed: {e}")

279

280

env.close()

281

```

282

283

#### Multi-Database Transactions

284

285

```python

286

import lmdb

287

288

env = lmdb.open('/path/to/database', max_dbs=3)

289

290

# Open multiple databases

291

users_db = env.open_db(b'users')

292

posts_db = env.open_db(b'posts')

293

comments_db = env.open_db(b'comments')

294

295

# Atomic operations across multiple databases

296

with env.begin(write=True) as txn:

297

# Create user

298

user_id = b'user:123'

299

txn.put(user_id, b'{"name": "Alice"}', db=users_db)

300

301

# Create post by user

302

post_id = b'post:456'

303

txn.put(post_id, b'{"user_id": "123", "title": "Hello World"}', db=posts_db)

304

305

# Add comment to post

306

comment_id = b'comment:789'

307

txn.put(comment_id, b'{"post_id": "456", "text": "Great post!"}', db=comments_db)

308

309

# All operations committed atomically

310

311

# Read from multiple databases

312

with env.begin() as txn:

313

user = txn.get(b'user:123', db=users_db)

314

post = txn.get(b'post:456', db=posts_db)

315

comment = txn.get(b'comment:789', db=comments_db)

316

317

print(f"User: {user}")

318

print(f"Post: {post}")

319

print(f"Comment: {comment}")

320

321

env.close()

322

```

323

324

#### Error Handling

325

326

```python

327

import lmdb

328

329

env = lmdb.open('/path/to/database')

330

331

try:

332

with env.begin(write=True) as txn:

333

txn.put(b'key1', b'value1')

334

335

# This might fail if database is full

336

large_value = b'x' * 1000000

337

txn.put(b'large_key', large_value)

338

339

except lmdb.MapFullError:

340

print("Database is full - increase map_size")

341

342

except lmdb.Error as e:

343

print(f"LMDB error: {e}")

344

345

finally:

346

env.close()

347

```