1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
| #include <sys/uio.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <fcntl.h> #include <time.h> #include <sys/stat.h>
/** * 事务操作类型 */ typedef enum { TXN_BEGIN = 1, TXN_COMMIT = 2, TXN_ROLLBACK = 3, TXN_INSERT = 4, TXN_UPDATE = 5, TXN_DELETE = 6 } txn_operation_t;
/** * 事务日志条目 */ typedef struct { txn_operation_t operation; time_t timestamp; unsigned long transaction_id; const char *table_name; const char *data; size_t data_size; } txn_log_entry_t;
/** * 事务日志管理器 */ typedef struct { int log_fd; char log_filename[256]; struct iovec *iov_buffer; int buffer_capacity; int buffer_count; size_t buffer_size; unsigned long current_txn_id; } txn_log_manager_t;
/** * 初始化事务日志管理器 */ int init_txn_log_manager(txn_log_manager_t *manager, const char *log_dir) { // 创建日志目录 struct stat st = {0}; if (stat(log_dir, &st) == -1) { if (mkdir(log_dir, 0755) == -1) { perror("创建日志目录失败"); return -1; } } // 初始化管理器 snprintf(manager->log_filename, sizeof(manager->log_filename), "%s/transaction.log", log_dir); manager->log_fd = open(manager->log_filename, O_CREAT | O_WRONLY | O_APPEND, 0644); if (manager->log_fd == -1) { perror("创建事务日志文件失败"); return -1; } manager->buffer_capacity = 64; manager->iov_buffer = malloc(manager->buffer_capacity * sizeof(struct iovec)); if (!manager->iov_buffer) { close(manager->log_fd); return -1; } manager->buffer_count = 0; manager->buffer_size = 0; manager->current_txn_id = time(NULL); // 简单的事务ID生成 printf("事务日志管理器初始化完成:\n"); printf(" 日志文件: %s\n", manager->log_filename); printf(" 缓冲区容量: %d\n", manager->buffer_capacity); printf(" 初始事务ID: %lu\n", manager->current_txn_id); return 0; }
/** * 格式化事务日志条目 */ char* format_txn_log_entry(const txn_log_entry_t *entry) { char *buffer = malloc(512); if (!buffer) { return NULL; } struct tm *tm_info = localtime(&entry->timestamp); char time_str[32]; strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", tm_info); const char *op_names[] = { "", "BEGIN", "COMMIT", "ROLLBACK", "INSERT", "UPDATE", "DELETE" }; snprintf(buffer, 512, "[%s] TXN:%lu OP:%s TABLE:%s SIZE:%zu DATA:%s\n", time_str, entry->transaction_id, op_names[entry->operation], entry->table_name ? entry->table_name : "N/A", entry->data_size, entry->data ? entry->data : ""); return buffer; }
/** * 添加事务日志条目 */ int add_txn_log_entry(txn_log_manager_t *manager, const txn_log_entry_t *entry) { if (manager->buffer_count >= manager->buffer_capacity) { printf("事务日志缓冲区已满,需要冲刷\n"); if (flush_txn_log_buffer(manager) != 0) { return -1; } } char *formatted_entry = format_txn_log_entry(entry); if (!formatted_entry) { return -1; } manager->iov_buffer[manager->buffer_count].iov_base = formatted_entry; manager->iov_buffer[manager->buffer_count].iov_len = strlen(formatted_entry); manager->buffer_size += manager->iov_buffer[manager->buffer_count].iov_len; manager->buffer_count++; printf("添加事务日志条目: TXN:%lu OP:%d\n", entry->transaction_id, entry->operation); return 0; }
/** * 冲刷事务日志缓冲区 */ int flush_txn_log_buffer(txn_log_manager_t *manager) { if (manager->buffer_count == 0) { return 0; } printf("冲刷事务日志缓冲区: %d 条目, %zu 字节\n", manager->buffer_count, manager->buffer_size); ssize_t bytes_written = writev(manager->log_fd, manager->iov_buffer, manager->buffer_count); if (bytes_written == -1) { perror("写入事务日志失败"); return -1; } printf(" 成功写入 %zd 字节事务日志\n", bytes_written); // 清理内存 for (int i = 0; i < manager->buffer_count; i++) { free(manager->iov_buffer[i].iov_base); } manager->buffer_count = 0; manager->buffer_size = 0; // 同步到磁盘 fsync(manager->log_fd); return 0; }
/** * 演示数据库事务日志 */ int demo_database_transaction_log() { txn_log_manager_t log_manager; const char *log_directory = "./txn_logs"; printf("=== 数据库事务日志演示 ===\n"); // 初始化事务日志管理器 printf("1. 初始化事务日志管理器:\n"); if (init_txn_log_manager(&log_manager, log_directory) != 0) { printf("初始化事务日志管理器失败\n"); return -1; } // 模拟数据库事务操作 printf("\n2. 模拟数据库事务操作:\n"); // 事务1: 插入操作 printf(" 事务1: 数据插入操作\n"); txn_log_entry_t insert_entry = { .operation = TXN_BEGIN, .timestamp = time(NULL), .transaction_id = log_manager.current_txn_id++, .table_name = "users", .data = "{'name':'John','email':'john@example.com'}", .data_size = 45 }; add_txn_log_entry(&log_manager, &insert_entry); txn_log_entry_t insert_data = { .operation = TXN_INSERT, .timestamp = time(NULL), .transaction_id = insert_entry.transaction_id, .table_name = "users", .data = "INSERT INTO users VALUES ('John', 'john@example.com')", .data_size = 52 }; add_txn_log_entry(&log_manager, &insert_data); txn_log_entry_t commit_entry = { .operation = TXN_COMMIT, .timestamp = time(NULL), .transaction_id = insert_entry.transaction_id, .table_name = "users", .data = "Transaction committed successfully", .data_size = 32 }; add_txn_log_entry(&log_manager, &commit_entry); // 冲刷第一个事务 flush_txn_log_buffer(&log_manager); // 事务2: 更新操作 printf("\n 事务2: 数据更新操作\n"); txn_log_entry_t update_entry = { .operation = TXN_BEGIN, .timestamp = time(NULL), .transaction_id = log_manager.current_txn_id++, .table_name = "orders", .data = "{'order_id':12345,'status':'processing'}", .data_size = 42 }; add_txn_log_entry(&log_manager, &update_entry); txn_log_entry_t update_data = { .operation = TXN_UPDATE, .timestamp = time(NULL), .transaction_id = update_entry.transaction_id, .table_name = "orders", .data = "UPDATE orders SET status='shipped' WHERE order_id=12345", .data_size = 55 }; add_txn_log_entry(&log_manager, &update_data); // 事务3: 删除操作(在同一事务中) txn_log_entry_t delete_data = { .operation = TXN_DELETE, .timestamp = time(NULL), .transaction_id = update_entry.transaction_id, .table_name = "cart_items", .data = "DELETE FROM cart_items WHERE user_id=1001", .data_size = 43 }; add_txn_log_entry(&log_manager, &delete_data); txn_log_entry_t commit_update = { .operation = TXN_COMMIT, .timestamp = time(NULL), .transaction_id = update_entry.transaction_id, .table_name = "orders", .data = "Multi-table transaction committed", .data_size = 35 }; add_txn_log_entry(&log_manager, &commit_update); // 事务4: 回滚操作 printf("\n 事务3: 事务回滚操作\n"); txn_log_entry_t rollback_entry = { .operation = TXN_BEGIN, .timestamp = time(NULL), .transaction_id = log_manager.current_txn_id++, .table_name = "inventory", .data = "Stock adjustment transaction", .data_size = 28 }; add_txn_log_entry(&log_manager, &rollback_entry); txn_log_entry_t error_entry = { .operation = TXN_UPDATE, .timestamp = time(NULL), .transaction_id = rollback_entry.transaction_id, .table_name = "inventory", .data = "UPDATE inventory SET quantity=-5 WHERE product_id=100", // 错误:负库存 .data_size = 57 }; add_txn_log_entry(&log_manager, &error_entry); txn_log_entry_t rollback_txn = { .operation = TXN_ROLLBACK, .timestamp = time(NULL), .transaction_id = rollback_entry.transaction_id, .table_name = "inventory", .data = "Rollback due to negative stock adjustment", .data_size = 45 }; add_txn_log_entry(&log_manager, &rollback_txn); // 最终冲刷 printf("\n3. 最终冲刷剩余日志:\n"); flush_txn_log_buffer(&log_manager); // 验证日志文件 printf("\n4. 验证事务日志文件:\n"); int fd = open(log_manager.log_filename, O_RDONLY); if (fd != -1) { char buffer[2048]; ssize_t bytes_read = read(fd, buffer, sizeof(buffer) - 1); if (bytes_read > 0) { buffer[bytes_read] = '\0'; printf(" 事务日志内容 (%zd 字节):\n", bytes_read); // 显示日志内容 char *line = strtok(buffer, "\n"); while (line) { printf(" %s\n", line); line = strtok(NULL, "\n"); } } close(fd); } // 清理资源 if (log_manager.iov_buffer) { // 清理可能残留的缓冲区条目 for (int i = 0; i < log_manager.buffer_count; i++) { free(log_manager.iov_buffer[i].iov_base); } free(log_manager.iov_buffer); } if (log_manager.log_fd != -1) { close(log_manager.log_fd); } // 清理日志文件 unlink(log_manager.log_filename); rmdir(log_directory); // 显示事务日志优势 printf("\n=== 事务日志优势 ===\n"); printf("1. ACID特性保证:\n"); printf(" ✓ 原子性: 事务操作要么全部成功要么全部失败\n"); printf(" ✓ 一致性: 系统从一个一致状态转换到另一个一致状态\n"); printf(" ✓ 隔离性: 并发事务之间相互隔离\n"); printf(" ✓ 持久性: 事务提交后对数据的修改是永久性的\n"); printf("\n2. 性能优化:\n"); printf(" ✓ 批量日志写入减少I/O操作\n"); printf(" ✓ 零拷贝数据组装提高效率\n"); printf(" ✓ 缓冲机制减少系统调用开销\n"); printf(" ✓ 异步写入提高响应速度\n"); printf("\n3. 可靠性保障:\n"); printf(" ✓ 完整的事务轨迹记录\n"); printf(" ✓ 快速故障恢复能力\n"); printf(" ✓ 数据一致性验证\n"); printf(" ✓ 审计和合规支持\n"); return 0; }
int main() { return demo_database_transaction_log(); }
|