mm_mysql 2.3.8 → 2.4.0

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 (2) hide show
  1. package/index.js +96 -386
  2. package/package.json +1 -1
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>}
@@ -353,98 +207,26 @@ Mysql.prototype.run = async function (sql, params = []) {
353
207
  }
354
208
 
355
209
  this.error = null;
210
+ this.sql = '';
356
211
  let conn = null;
357
- let is_pool_conn = false;
358
- let connection_released = false;
359
-
212
+ let ret = [];
360
213
  try {
361
214
  // 获取连接
362
215
  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
- }
216
+ this.sql = sql;
217
+ let [rows] = await conn.query(sql, params);
218
+ ret = rows;
421
219
  } catch (err) {
422
220
  this.sql = err.sql;
423
221
  this.error = {
424
222
  code: err.errno,
425
223
  message: err.sqlMessage
426
224
  };
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
225
  }
447
- return [];
226
+ finally {
227
+ await releaseConn(conn);
228
+ }
229
+ return ret;
448
230
  };
449
231
 
450
232
  /**
@@ -463,71 +245,15 @@ Mysql.prototype.exec = async function (sql, params = []) {
463
245
  throw new TypeError('params must be array');
464
246
  }
465
247
  this.error = null;
248
+ this.sql = '';
466
249
  let conn = null;
467
- let is_pool_conn = false;
468
- let connection_released = false;
469
-
250
+ let ret = 0;
470
251
  try {
471
252
  // 获取连接
472
253
  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
- }
254
+ this.sql = sql;
255
+ let [result] = await conn.execute(sql, params);
256
+ ret = result.insertId || result.affectedRows || result.changedRows || 1;
531
257
  } catch (error) {
532
258
  this.log('error', 'SQL执行失败', error);
533
259
  this.sql = error.sql;
@@ -535,27 +261,11 @@ Mysql.prototype.exec = async function (sql, params = []) {
535
261
  code: error.errno,
536
262
  message: error.sqlMessage
537
263
  };
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
264
  }
558
- return 0;
265
+ finally {
266
+ await releaseConn(conn);
267
+ }
268
+ return ret;
559
269
  };
560
270
 
561
271
  /**
@@ -563,32 +273,32 @@ Mysql.prototype.exec = async function (sql, params = []) {
563
273
  * @returns {Promise<object>} 事务连接对象
564
274
  */
565
275
  Mysql.prototype.beginTransaction = async function () {
566
- const conn = await this.getConn();
567
-
276
+ let conn = await this.getConn();
277
+
568
278
  try {
569
279
  await conn.beginTransaction();
570
-
280
+
571
281
  let ended = false;
572
-
282
+
573
283
  return {
574
284
  connection: conn,
575
285
  commit: async () => {
576
286
  if (ended) return;
577
287
  await conn.commit();
578
288
  ended = true;
579
- await this._releaseConn(conn);
289
+ await releaseConn(conn);
580
290
  },
581
291
  rollback: async () => {
582
292
  if (ended) return;
583
293
  await conn.rollback();
584
294
  ended = true;
585
- await this._releaseConn(conn);
295
+ await releaseConn(conn);
586
296
  },
587
297
  _is_ended: () => ended
588
298
  };
589
299
  } catch (error) {
590
300
  // 如果事务开始失败,确保连接被释放
591
- await this._releaseConn(conn);
301
+ await releaseConn(conn);
592
302
  this.log('error', '事务开始失败', error);
593
303
  throw error;
594
304
  }
@@ -605,16 +315,16 @@ Mysql.prototype.transaction = async function (callback) {
605
315
  throw new TypeError('callback must be function');
606
316
  }
607
317
 
608
- const transaction = await this.beginTransaction();
609
-
318
+ let transaction = await this.beginTransaction();
319
+
610
320
  try {
611
- const result = await callback(transaction);
612
-
321
+ let result = await callback(transaction);
322
+
613
323
  // 如果事务未结束,自动提交
614
324
  if (!transaction._is_ended()) {
615
325
  await transaction.commit();
616
326
  }
617
-
327
+
618
328
  return result;
619
329
  } catch (error) {
620
330
  // 如果事务未结束,自动回滚
@@ -623,7 +333,7 @@ Mysql.prototype.transaction = async function (callback) {
623
333
  // 简化错误处理,避免频繁日志
624
334
  });
625
335
  }
626
-
336
+
627
337
  throw error;
628
338
  }
629
339
  };
@@ -650,12 +360,12 @@ Mysql.prototype.read = async function (table, condition = {}, options = {}) {
650
360
 
651
361
  try {
652
362
  let sql = `SELECT * FROM ${table}`;
653
- const params = [];
363
+ let params = [];
654
364
 
655
365
  // 处理条件
656
366
  if (Object.keys(condition).length > 0) {
657
- const whereClauses = [];
658
- for (const [field, value] of Object.entries(condition)) {
367
+ let whereClauses = [];
368
+ for (let [field, value] of Object.entries(condition)) {
659
369
  whereClauses.push(`${field} = ?`);
660
370
  params.push(value);
661
371
  }
@@ -715,7 +425,7 @@ Mysql.prototype.healthCheck = async function () {
715
425
  }
716
426
 
717
427
  // 执行简单的查询来检查连接状态
718
- const result = await this.run('SELECT 1 as health_check');
428
+ let result = await this.run('SELECT 1 as health_check');
719
429
 
720
430
  if (result && result.length > 0 && result[0].health_check === 1) {
721
431
  return {
@@ -787,7 +497,7 @@ function _acquireLock(key) {
787
497
  }
788
498
 
789
499
  let release;
790
- const lockPromise = $.pool.mysql._locks[key].then(() => {
500
+ let lockPromise = $.pool.mysql._locks[key].then(() => {
791
501
  return new Promise(resolve => {
792
502
  release = resolve;
793
503
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mm_mysql",
3
- "version": "2.3.8",
3
+ "version": "2.4.0",
4
4
  "description": "这是超级美眉mysql帮助函数模块,用于便捷操作mysql,使用await方式,可以避免嵌套函数",
5
5
  "main": "index.js",
6
6
  "dependencies": {