mm_mysql 2.3.7 → 2.3.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/db.js +11 -11
  2. package/index.js +92 -386
  3. package/package.json +1 -1
package/db.js CHANGED
@@ -62,12 +62,12 @@ DB.prototype.database = function () {
62
62
  * @param {string} key 键名
63
63
  * @returns {object} 返回管理器
64
64
  */
65
- DB.prototype.new = function (table, key) {
65
+ DB.prototype.new = function (table = '', key = '') {
66
66
  const db = this.getParent().db();
67
67
  db.table = table;
68
68
  if (key) {
69
69
  db.key = key;
70
- } else {
70
+ } else if (table) {
71
71
  const arr = table.split('_');
72
72
  db.key = arr[arr.length - 1] + '_id';
73
73
  }
@@ -78,7 +78,7 @@ DB.prototype.new = function (table, key) {
78
78
  * 获取数据库连接
79
79
  * @returns {Promise<object>}
80
80
  */
81
- DB.prototype.getConn = async function() {
81
+ DB.prototype.getConn = async function () {
82
82
  try {
83
83
  return await this.getParent().getConn();
84
84
  } catch (error) {
@@ -92,7 +92,7 @@ DB.prototype.getConn = async function() {
92
92
  * 开始事务
93
93
  * @returns {Promise<object>}
94
94
  */
95
- DB.prototype.start = async function() {
95
+ DB.prototype.start = async function () {
96
96
  try {
97
97
  return await this.getParent().beginTransaction();
98
98
  } catch (error) {
@@ -108,12 +108,12 @@ DB.prototype.start = async function() {
108
108
  * @returns {Promise<void>}
109
109
  * @throws {TypeError} 当transaction参数无效时
110
110
  */
111
- DB.prototype.commit = async function(transaction) {
111
+ DB.prototype.commit = async function (transaction) {
112
112
  // 参数校验
113
113
  if (!transaction || typeof transaction !== 'object') {
114
114
  throw new TypeError('transaction must be object');
115
115
  }
116
-
116
+
117
117
  try {
118
118
  await transaction.commit();
119
119
  } catch (error) {
@@ -127,12 +127,12 @@ DB.prototype.commit = async function(transaction) {
127
127
  * @returns {Promise<void>}
128
128
  * @throws {TypeError} 当transaction参数无效时
129
129
  */
130
- DB.prototype.back = async function(transaction) {
130
+ DB.prototype.back = async function (transaction) {
131
131
  // 参数校验
132
132
  if (!transaction || typeof transaction !== 'object') {
133
133
  throw new TypeError('transaction must be object');
134
134
  }
135
-
135
+
136
136
  try {
137
137
  await transaction.rollback();
138
138
  } catch (error) {
@@ -146,12 +146,12 @@ DB.prototype.back = async function(transaction) {
146
146
  * @returns {Promise<*>}
147
147
  * @throws {TypeError} 当callback参数无效时
148
148
  */
149
- DB.prototype.transaction = async function(callback) {
149
+ DB.prototype.transaction = async function (callback) {
150
150
  // 参数校验
151
151
  if (typeof callback !== 'function') {
152
152
  throw new TypeError('callback must be function');
153
153
  }
154
-
154
+
155
155
  try {
156
156
  return await this.getParent().transaction(callback);
157
157
  } catch (error) {
@@ -205,7 +205,7 @@ DB.prototype.fields = async function (table, field_name, timeout = 15000) {
205
205
  }
206
206
  const field = 'COLUMN_NAME as `name`,ORDINAL_POSITION as `cid`,COLUMN_DEFAULT as `default_value`,IS_NULLABLE as `not_null`,COLUMN_TYPE as `type`,COLUMN_KEY as `pk`,EXTRA as `auto`,COLUMN_COMMENT as `note`';
207
207
  let sql = 'select ' + field + " from information_schema.COLUMNS where `table_name` = '" + targetTable +
208
- "' and `table_schema` = '" + this.database() + "'";
208
+ "' and `table_schema` = '" + this.database() + "'";
209
209
  if (field_name) {
210
210
  sql += " AND COLUMN_NAME='" + field_name + "'";
211
211
  }
package/index.js CHANGED
@@ -22,7 +22,7 @@ class Mysql extends Base {
22
22
  charset: 'utf8mb4',
23
23
  timezone: '+08:00',
24
24
  connect_timeout: 15000,
25
-
25
+
26
26
  // 连接池优化配置(针对高并发写入场景)
27
27
  connection_limit: 100, // 减少连接数,避免资源竞争
28
28
  acquire_timeout: 30000, // 延长获取连接超时时间
@@ -30,11 +30,6 @@ class Mysql extends Base {
30
30
  idle_timeout: 300000, // 延长空闲连接超时时间(5分钟)
31
31
  max_idle: 30, // 减少最大空闲连接数
32
32
  queue_timeout: 60000, // 队列超时时间
33
-
34
- // 预处理语句缓存优化配置
35
- statement_cache_size: 50, // 减少缓存大小,避免内存泄漏
36
- max_prepared_statement_age: 300000, // 延长过期时间(5分钟)
37
- enable_statement_pooling: true // 启用预处理语句缓存
38
33
  };
39
34
 
40
35
  /**
@@ -45,130 +40,14 @@ class Mysql extends Base {
45
40
  super(config);
46
41
  this._pool = null;
47
42
  // 移除单连接支持,统一使用连接池
48
- this._use_pool = true; // 强制使用连接池模式
49
-
43
+
50
44
  // 错误信息
51
45
  this.error = null;
52
46
  // 最近执行的SQL语句
53
47
  this.sql = '';
54
-
55
- // 预处理语句缓存
56
- this._prepared_stmts = new Map();
57
- this._stmt_cache_size = this.config.statement_cache_size || 100;
58
- this._cache_hits = 0;
59
- this._cache_misses = 0;
60
-
61
- // 启动定期清理任务
62
- this._startCleanupTask();
63
48
  }
64
49
  }
65
50
 
66
- /**
67
- * 启动预处理语句清理任务
68
- * @private
69
- */
70
- Mysql.prototype._startCleanupTask = function() {
71
- if (this._cleanup_interval) {
72
- clearInterval(this._cleanup_interval);
73
- }
74
-
75
- this._cleanup_interval = setInterval(() => {
76
- this._cleanupExpiredStatements();
77
- }, 60000); // 每分钟清理一次
78
- };
79
-
80
- /**
81
- * 清理过期预处理语句
82
- * @private
83
- */
84
- Mysql.prototype._cleanupExpiredStatements = function() {
85
- const now = Date.now();
86
- const max_age = this.config.max_prepared_statement_age || 300000;
87
-
88
- for (const [key, statement_info] of this._prepared_stmts) {
89
- if (now - statement_info.last_used > max_age) {
90
- // 异步关闭语句,不阻塞主线程
91
- if (statement_info.statement && typeof statement_info.statement.close === 'function') {
92
- statement_info.statement.close().catch(() => {});
93
- }
94
- this._prepared_stmts.delete(key);
95
- }
96
- }
97
- };
98
-
99
- /**
100
- * 生成预处理语句缓存键
101
- * @private
102
- * @param {string} sql - SQL语句
103
- * @returns {string} 缓存键
104
- */
105
- Mysql.prototype._getStatementCacheKey = function(sql) {
106
- // 简化SQL语句,移除多余空格和换行,提高缓存命中率
107
- return sql.trim().replace(/\s+/g, ' ').toLowerCase();
108
- };
109
-
110
- /**
111
- * 缓存预处理语句
112
- * @private
113
- * @param {string} key - 缓存键
114
- * @param {object} statement - 预处理语句对象
115
- */
116
- Mysql.prototype._cacheStatement = function(key, statement) {
117
- if (this._prepared_stmts.size >= this._stmt_cache_size) {
118
- // 移除最久未使用的语句
119
- const oldest_key = this._findOldestStatement();
120
- if (oldest_key) {
121
- const oldest_statement = this._prepared_stmts.get(oldest_key);
122
- if (oldest_statement.statement && typeof oldest_statement.statement.close === 'function') {
123
- oldest_statement.statement.close().catch(() => {});
124
- }
125
- this._prepared_stmts.delete(oldest_key);
126
- }
127
- }
128
-
129
- this._prepared_stmts.set(key, {
130
- statement: statement,
131
- last_used: Date.now(),
132
- use_count: 0
133
- });
134
- };
135
-
136
- /**
137
- * 查找最久未使用的预处理语句
138
- * @private
139
- * @returns {string} 缓存键
140
- */
141
- Mysql.prototype._findOldestStatement = function() {
142
- let oldest_key = null;
143
- let oldest_time = Date.now();
144
-
145
- for (const [key, statement_info] of this._prepared_stmts) {
146
- if (statement_info.last_used < oldest_time) {
147
- oldest_time = statement_info.last_used;
148
- oldest_key = key;
149
- }
150
- }
151
-
152
- return oldest_key;
153
- };
154
-
155
- /**
156
- * 获取预处理语句缓存统计信息
157
- * @returns {object} 统计信息
158
- */
159
- Mysql.prototype.getStatementStats = function() {
160
- const total = this._cache_hits + this._cache_misses;
161
- const hit_rate = total > 0 ? (this._cache_hits / total) * 100 : 0;
162
-
163
- return {
164
- cached_statements: this._prepared_stmts.size,
165
- cache_hits: this._cache_hits,
166
- cache_misses: this._cache_misses,
167
- cache_hit_rate: hit_rate.toFixed(2) + '%',
168
- max_cache_size: this._stmt_cache_size
169
- };
170
- };
171
-
172
51
  /**
173
52
  * 获取MySQL2支持的配置参数
174
53
  * 根据连接类型(连接池或单连接)过滤参数,避免警告
@@ -177,7 +56,7 @@ Mysql.prototype.getStatementStats = function() {
177
56
  */
178
57
  Mysql.prototype._getValidConfig = function (is_pool = false) {
179
58
  // 基础连接参数(适用于所有连接类型)
180
- const base_map = {
59
+ let base_map = {
181
60
  'host': 'host',
182
61
  'port': 'port',
183
62
  'user': 'user',
@@ -189,17 +68,17 @@ Mysql.prototype._getValidConfig = function (is_pool = false) {
189
68
  };
190
69
 
191
70
  // 连接池专用参数
192
- const pool_map = {
71
+ let pool_map = {
193
72
  'connection_limit': 'connectionLimit',
194
73
  'wait_for_connections': 'waitForConnections',
195
74
  'idle_timeout': 'idleTimeout',
196
75
  'max_idle': 'maxIdle'
197
76
  };
198
77
 
199
- const config = {};
78
+ let config = {};
200
79
 
201
80
  // 添加基础参数
202
- for (const key in base_map) {
81
+ for (let key in base_map) {
203
82
  if (this.config[key] !== undefined) {
204
83
  config[base_map[key]] = this.config[key];
205
84
  }
@@ -207,7 +86,7 @@ Mysql.prototype._getValidConfig = function (is_pool = false) {
207
86
 
208
87
  // 如果是连接池,添加连接池专用参数
209
88
  if (is_pool) {
210
- for (const key in pool_map) {
89
+ for (let key in pool_map) {
211
90
  if (this.config[key] !== undefined) {
212
91
  config[pool_map[key]] = this.config[key];
213
92
  }
@@ -216,7 +95,7 @@ Mysql.prototype._getValidConfig = function (is_pool = false) {
216
95
  // 如果是单连接,确保不包含任何连接池专用参数
217
96
  else {
218
97
  // 移除所有连接池专用参数,避免mysql2内部警告
219
- for (const key in pool_map) {
98
+ for (let key in pool_map) {
220
99
  if (pool_map[key] in config) {
221
100
  delete config[pool_map[key]];
222
101
  }
@@ -231,87 +110,63 @@ Mysql.prototype._getValidConfig = function (is_pool = false) {
231
110
  * @returns {Promise<boolean>}
232
111
  * @throws {TypeError} 当配置参数无效时
233
112
  */
234
- Mysql.prototype.open = async function () {
235
- // 参数校验
236
- if (!this.config || typeof this.config !== 'object') {
237
- throw new TypeError('config must be object');
238
- }
113
+ Mysql.prototype.open = async function () {
114
+ // 参数校验
115
+ if (!this.config || typeof this.config !== 'object') {
116
+ throw new TypeError('config must be object');
117
+ }
239
118
 
240
- try {
241
- // 统一使用连接池模式
242
- const valid_config = this._getValidConfig(true);
243
- this._pool = mysql.createPool(valid_config);
244
-
245
- // 测试连接池连接
246
- const conn = await this._pool.getConnection();
247
- conn.release();
248
-
249
- this.log('info', '数据库连接池创建成功');
250
- return true;
251
- } catch (error) {
252
- this.log('error', '数据库连接池创建失败', error);
253
- return false;
254
- }
255
- };
119
+ try {
120
+ // 统一使用连接池模式
121
+ let valid_config = this._getValidConfig(true);
122
+ this._pool = mysql.createPool(valid_config);
256
123
 
257
- /**
258
- * 关闭数据库连接(统一使用连接池)
259
- * @returns {Promise<boolean>}
260
- */
261
- Mysql.prototype.close = async function () {
262
- try {
263
- // 先关闭连接池,再清理预处理语句(避免连接状态问题)
264
- if (this._pool) {
265
- await this._pool.end();
266
- this._pool = null;
267
- }
268
-
269
- // 连接池关闭后,预处理语句会自动失效,只需清理缓存
270
- if (this._prepared_stmts) {
271
- // 不再尝试关闭预处理语句,直接清空缓存
272
- this._prepared_stmts.clear();
273
- }
124
+ // 测试连接池连接
125
+ let conn = await this._pool.getConnection();
126
+ conn.release();
274
127
 
275
- this.log('info', '数据库连接池已关闭');
276
- return true;
277
- } catch (error) {
278
- this.log('error', '关闭连接池失败', error);
279
- return false;
280
- }
281
- };
128
+ this.log('info', '数据库连接池创建成功');
129
+ return true;
130
+ } catch (error) {
131
+ this.log('error', '数据库连接池创建失败', error);
132
+ return false;
133
+ }
134
+ };
282
135
 
283
136
  /**
284
- * 安全释放数据库连接
285
- * @param {object} conn - 数据库连接对象
286
- * @param {boolean} is_pool_conn - 是否为连接池连接
287
- * @returns {Promise<void>}
137
+ * 关闭数据库连接(统一使用连接池)
138
+ * @returns {Promise<boolean>}
288
139
  */
289
- async function safeReleaseConn(conn, is_pool_conn) {
290
- if (!conn) return;
291
-
140
+ Mysql.prototype.close = async function () {
292
141
  try {
293
- if (is_pool_conn && typeof conn.release === 'function') {
294
- await conn.release();
142
+ // 先关闭连接池(避免连接状态问题)
143
+ if (this._pool) {
144
+ await this._pool.end();
145
+ this._pool = null;
295
146
  }
296
- } catch (release_err) {
297
- $.log.error('释放连接失败', release_err);
147
+
148
+ this.log('info', '数据库连接池已关闭');
149
+ return true;
150
+ } catch (error) {
151
+ this.log('error', '关闭连接池失败', error);
152
+ return false;
298
153
  }
299
154
  };
300
155
 
301
156
  /**
302
- * 释放连接(实例方法,简化事务使用)
157
+ * 安全释放数据库连接
303
158
  * @param {object} conn - 数据库连接对象
304
159
  * @returns {Promise<void>}
305
160
  */
306
- Mysql.prototype._releaseConn = async function(conn) {
161
+ async function releaseConn(conn) {
307
162
  if (!conn) return;
308
-
163
+
309
164
  try {
310
- if (this._use_pool && typeof conn.release === 'function') {
165
+ if (typeof conn.release === 'function') {
311
166
  await conn.release();
312
167
  }
313
- } catch (error) {
314
- // 简化错误处理,避免频繁日志
168
+ } catch (release_err) {
169
+ $.log.error('释放连接失败', release_err);
315
170
  }
316
171
  };
317
172
 
@@ -320,24 +175,23 @@ Mysql.prototype._releaseConn = async function(conn) {
320
175
  * @returns {Promise<object>}
321
176
  * @throws {TypeError} 当连接池不存在时
322
177
  */
323
- Mysql.prototype.getConn = async function () {
324
- // 参数校验
325
- if (!this._pool) {
326
- await this.open();
327
- }
178
+ Mysql.prototype.getConn = async function () {
179
+ // 参数校验
180
+ if (!this._pool) {
181
+ await this.open();
182
+ }
328
183
 
329
- try {
330
- // 统一从连接池获取连接
331
- const conn = await this._pool.getConnection();
332
- return conn;
333
- } catch (error) {
334
- this.log('error', '从连接池获取连接失败', error);
335
- throw error; // 重新抛出错误,让调用方处理
336
- }
337
- };
184
+ try {
185
+ // 统一从连接池获取连接
186
+ return await this._pool.getConnection();
187
+ } catch (error) {
188
+ this.log('error', '从连接池获取连接失败', error);
189
+ throw error; // 重新抛出错误,让调用方处理
190
+ }
191
+ };
338
192
 
339
193
  /**
340
- * 执行SQL查询(优化版,支持预处理语句缓存)
194
+ * 执行SQL查询
341
195
  * @param {string} sql - SQL语句
342
196
  * @param {Array} params - 参数数组
343
197
  * @returns {Promise<object>}
@@ -354,97 +208,23 @@ Mysql.prototype.run = async function (sql, params = []) {
354
208
 
355
209
  this.error = null;
356
210
  let conn = null;
357
- let is_pool_conn = false;
358
- let connection_released = false;
359
-
211
+ let ret = [];
360
212
  try {
361
213
  // 获取连接
362
214
  conn = await this.getConn();
363
- is_pool_conn = this._use_pool;
364
-
365
- // 检查是否启用预处理语句缓存
366
- if (this.config.enable_statement_pooling && params.length > 0) {
367
- const cache_key = this._getStatementCacheKey(sql);
368
- let statement_info = this._prepared_stmts.get(cache_key);
369
-
370
- if (statement_info && statement_info.statement) {
371
- // 使用缓存的预处理语句
372
- this._cache_hits++;
373
- statement_info.last_used = Date.now();
374
- statement_info.use_count++;
375
-
376
- // 预先检查连接状态,避免不必要的错误
377
- if (!conn || conn._fatalError || conn._closed) {
378
- conn = await this.getConn();
379
- // 连接已更新,需要重新创建预处理语句
380
- this._prepared_stmts.delete(cache_key);
381
- const statement = await conn.prepare(sql);
382
- this._cacheStatement(cache_key, statement);
383
- const [rows] = await statement.execute(params);
384
- return rows;
385
- }
386
-
387
- try {
388
- const [rows] = await statement_info.statement.execute(params);
389
- return rows;
390
- } catch (stmt_err) {
391
- // 预处理语句可能已失效(连接关闭等),重新创建
392
- this.log('warn', '预处理语句执行失败,重新创建', stmt_err);
393
- this._prepared_stmts.delete(cache_key);
394
-
395
- // 检查连接是否有效,如果无效则重新获取连接
396
- if (!conn || conn._fatalError || conn._closed) {
397
- conn = await this.getConn();
398
- }
399
-
400
- // 重新创建预处理语句
401
- const statement = await conn.prepare(sql);
402
- this._cacheStatement(cache_key, statement);
403
-
404
- const [rows] = await statement.execute(params);
405
- return rows;
406
- }
407
- } else {
408
- // 创建新的预处理语句并缓存
409
- this._cache_misses++;
410
- const statement = await conn.prepare(sql);
411
- this._cacheStatement(cache_key, statement);
412
-
413
- const [rows] = await statement.execute(params);
414
- return rows;
415
- }
416
- } else {
417
- // 不使用预处理语句缓存,直接查询
418
- const [rows] = await conn.query(sql, params);
419
- return rows;
420
- }
215
+ let [rows] = await conn.query(sql, params);
216
+ ret = rows;
421
217
  } catch (err) {
422
218
  this.sql = err.sql;
423
219
  this.error = {
424
220
  code: err.errno,
425
221
  message: err.sqlMessage
426
222
  };
427
- // 在错误情况下也要确保连接释放
428
- try {
429
- await safeReleaseConn(conn, is_pool_conn);
430
- } catch (release_err) {
431
- this.log('error', '释放连接失败', release_err);
432
- }
433
- connection_released = true;
434
-
435
- // 重新抛出错误,让调用方处理
436
- throw err;
437
- } finally {
438
- // 确保连接被释放,避免资源泄漏
439
- if (!connection_released) {
440
- try {
441
- await safeReleaseConn(conn, is_pool_conn);
442
- } catch (release_err) {
443
- this.log('error', '释放连接失败', release_err);
444
- }
445
- }
446
223
  }
447
- return [];
224
+ finally {
225
+ await releaseConn(conn);
226
+ }
227
+ return ret;
448
228
  };
449
229
 
450
230
  /**
@@ -464,70 +244,12 @@ Mysql.prototype.exec = async function (sql, params = []) {
464
244
  }
465
245
  this.error = null;
466
246
  let conn = null;
467
- let is_pool_conn = false;
468
- let connection_released = false;
469
-
247
+ let ret = 0;
470
248
  try {
471
249
  // 获取连接
472
250
  conn = await this.getConn();
473
- is_pool_conn = this._use_pool;
474
-
475
- // 检查是否启用预处理语句缓存
476
- if (this.config.enable_statement_pooling && params.length > 0) {
477
- const cache_key = this._getStatementCacheKey(sql);
478
- let statement_info = this._prepared_stmts.get(cache_key);
479
-
480
- if (statement_info && statement_info.statement) {
481
- // 使用缓存的预处理语句
482
- this._cache_hits++;
483
- statement_info.last_used = Date.now();
484
- statement_info.use_count++;
485
-
486
- // 预先检查连接状态,避免不必要的错误
487
- if (!conn || conn._fatalError || conn._closed) {
488
- conn = await this.getConn();
489
- // 连接已更新,需要重新创建预处理语句
490
- this._prepared_stmts.delete(cache_key);
491
- const statement = await conn.prepare(sql);
492
- this._cacheStatement(cache_key, statement);
493
- const [result] = await statement.execute(params);
494
- return result.insertId || result.affectedRows || result.changedRows || 1;
495
- }
496
-
497
- try {
498
- const [result] = await statement_info.statement.execute(params);
499
- return result.insertId || result.affectedRows || result.changedRows || 1;
500
- } catch (stmt_err) {
501
- // 预处理语句可能已失效(连接关闭等),重新创建
502
- this.log('warn', '预处理语句执行失败,重新创建', stmt_err);
503
- this._prepared_stmts.delete(cache_key);
504
-
505
- // 检查连接是否有效,如果无效则重新获取连接
506
- if (!conn || conn._fatalError || conn._closed) {
507
- conn = await this.getConn();
508
- }
509
-
510
- // 重新创建预处理语句
511
- const statement = await conn.prepare(sql);
512
- this._cacheStatement(cache_key, statement);
513
-
514
- const [result] = await statement.execute(params);
515
- return result.insertId || result.affectedRows || result.changedRows || 1;
516
- }
517
- } else {
518
- // 创建新的预处理语句并缓存
519
- this._cache_misses++;
520
- const statement = await conn.prepare(sql);
521
- this._cacheStatement(cache_key, statement);
522
-
523
- const [result] = await statement.execute(params);
524
- return result.insertId || result.affectedRows || result.changedRows || 1;
525
- }
526
- } else {
527
- // 对于写入语句,直接执行(不使用预处理语句缓存)
528
- const [result] = await conn.execute(sql, params);
529
- return result.insertId || result.affectedRows || result.changedRows || 1;
530
- }
251
+ let [result] = await conn.execute(sql, params);
252
+ ret = result.insertId || result.affectedRows || result.changedRows || 1;
531
253
  } catch (error) {
532
254
  this.log('error', 'SQL执行失败', error);
533
255
  this.sql = error.sql;
@@ -535,27 +257,11 @@ Mysql.prototype.exec = async function (sql, params = []) {
535
257
  code: error.errno,
536
258
  message: error.sqlMessage
537
259
  };
538
- // 在错误情况下也要确保连接释放
539
- try {
540
- await safeReleaseConn(conn, is_pool_conn);
541
- } catch (release_err) {
542
- this.log('error', '释放连接失败', release_err);
543
- }
544
- connection_released = true;
545
-
546
- // 重新抛出错误,让调用方处理
547
- throw error;
548
- } finally {
549
- // 确保连接被释放,避免资源泄漏
550
- if (!connection_released) {
551
- try {
552
- await safeReleaseConn(conn, is_pool_conn);
553
- } catch (release_err) {
554
- this.log('error', '释放连接失败', release_err);
555
- }
556
- }
557
260
  }
558
- return 0;
261
+ finally {
262
+ await releaseConn(conn);
263
+ }
264
+ return ret;
559
265
  };
560
266
 
561
267
  /**
@@ -563,32 +269,32 @@ Mysql.prototype.exec = async function (sql, params = []) {
563
269
  * @returns {Promise<object>} 事务连接对象
564
270
  */
565
271
  Mysql.prototype.beginTransaction = async function () {
566
- const conn = await this.getConn();
567
-
272
+ let conn = await this.getConn();
273
+
568
274
  try {
569
275
  await conn.beginTransaction();
570
-
276
+
571
277
  let ended = false;
572
-
278
+
573
279
  return {
574
280
  connection: conn,
575
281
  commit: async () => {
576
282
  if (ended) return;
577
283
  await conn.commit();
578
284
  ended = true;
579
- await this._releaseConn(conn);
285
+ await releaseConn(conn);
580
286
  },
581
287
  rollback: async () => {
582
288
  if (ended) return;
583
289
  await conn.rollback();
584
290
  ended = true;
585
- await this._releaseConn(conn);
291
+ await releaseConn(conn);
586
292
  },
587
293
  _is_ended: () => ended
588
294
  };
589
295
  } catch (error) {
590
296
  // 如果事务开始失败,确保连接被释放
591
- await this._releaseConn(conn);
297
+ await releaseConn(conn);
592
298
  this.log('error', '事务开始失败', error);
593
299
  throw error;
594
300
  }
@@ -605,16 +311,16 @@ Mysql.prototype.transaction = async function (callback) {
605
311
  throw new TypeError('callback must be function');
606
312
  }
607
313
 
608
- const transaction = await this.beginTransaction();
609
-
314
+ let transaction = await this.beginTransaction();
315
+
610
316
  try {
611
- const result = await callback(transaction);
612
-
317
+ let result = await callback(transaction);
318
+
613
319
  // 如果事务未结束,自动提交
614
320
  if (!transaction._is_ended()) {
615
321
  await transaction.commit();
616
322
  }
617
-
323
+
618
324
  return result;
619
325
  } catch (error) {
620
326
  // 如果事务未结束,自动回滚
@@ -623,7 +329,7 @@ Mysql.prototype.transaction = async function (callback) {
623
329
  // 简化错误处理,避免频繁日志
624
330
  });
625
331
  }
626
-
332
+
627
333
  throw error;
628
334
  }
629
335
  };
@@ -650,12 +356,12 @@ Mysql.prototype.read = async function (table, condition = {}, options = {}) {
650
356
 
651
357
  try {
652
358
  let sql = `SELECT * FROM ${table}`;
653
- const params = [];
359
+ let params = [];
654
360
 
655
361
  // 处理条件
656
362
  if (Object.keys(condition).length > 0) {
657
- const whereClauses = [];
658
- for (const [field, value] of Object.entries(condition)) {
363
+ let whereClauses = [];
364
+ for (let [field, value] of Object.entries(condition)) {
659
365
  whereClauses.push(`${field} = ?`);
660
366
  params.push(value);
661
367
  }
@@ -715,7 +421,7 @@ Mysql.prototype.healthCheck = async function () {
715
421
  }
716
422
 
717
423
  // 执行简单的查询来检查连接状态
718
- const result = await this.run('SELECT 1 as health_check');
424
+ let result = await this.run('SELECT 1 as health_check');
719
425
 
720
426
  if (result && result.length > 0 && result[0].health_check === 1) {
721
427
  return {
@@ -787,7 +493,7 @@ function _acquireLock(key) {
787
493
  }
788
494
 
789
495
  let release;
790
- const lockPromise = $.pool.mysql._locks[key].then(() => {
496
+ let lockPromise = $.pool.mysql._locks[key].then(() => {
791
497
  return new Promise(resolve => {
792
498
  release = resolve;
793
499
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_mysql",
3
- "version": "2.3.7",
3
+ "version": "2.3.9",
4
4
  "description": "这是超级美眉mysql帮助函数模块,用于便捷操作mysql,使用await方式,可以避免嵌套函数",
5
5
  "main": "index.js",
6
6
  "dependencies": {