關於使用MySql出現的記憶體流失問題

來源:互聯網
上載者:User

標籤:

  最近做的東西使用了MySql做查詢排序等,但是一直出現問題,主要是出現在查詢的時候記憶體總是在增加,每次增加的記憶體大小是一樣的,

找了很多資料才知道原來是使用了mysql_store_result()後忘了釋放

  所以,記住由mysql_store_result()、mysql_use_result()、mysql_list_dbs()的結果集在完成對結果集的操作後,必須調用mysql_free_result()釋放結果集使用的記憶體。

  還有,每次查詢返回的結果的地址是不一樣的,所以必須釋放。

  下面附上mysql的一些操作函數

  轉至:http://blog.csdn.net/bichenggui/article/details/5944102

  mysql的結果集其實就是一個MYSQL_RES結構,其定義如下: 

typedef struct st_mysql_res {

  my_ulonglong row_count;                               // 結果集的行數

  unsigned int field_count, current_field;            // 結果集的列數,當前列

  MYSQL_FIELD *fields;                                    // 結果集的列資訊

  MYSQL_DATA *data;                                      // 結果集的資料

  MYSQL_ROWS *data_cursor;                        // 結果集的游標

  MEM_ROOT field_alloc;                                   // 記憶體結構

  MYSQL_ROW row;                                         // 非緩衝的時候用到

  MYSQL_ROW current_row;                           //mysql_store_result時會用到。當前行

  unsigned long *lengths;                                //每列的長度

  MYSQL *handle;                                           // mysql_use_result會用。

  my_bool eof;                                                 //是否為行尾

} MYSQL_RES;

typedef char ** MYSQL_ROW; /* 返回的每一行的值,全部用字串來表示*/typedef struct st_mysql_rows {  struct st_mysql_rows *next; /* list of rows */  MYSQL_ROW data;}  MYSQL_ROWS;        //mysql的資料的鏈表節點。可見mysql的結果集是鏈表結構typedef struct st_mysql_data {  my_ulonglong rows;  unsigned int fields;  MYSQL_ROWS *data;  MEM_ROOT alloc;}  MYSQL_DATA; // 資料集的結構typedef struct st_mysql_field {  char *name; /* Name of column */  char *table;                                            /* Table of column if column was a field */  char *def;                                               /* Default value (set by mysql_list_fields) */  enum enum_field_types type;                /* Type of field. Se mysql_com.h for types */  unsigned int length;                               /* Width of column */  unsigned int max_length;                       /* Max width of selected set */  unsigned int flags;                                  /* Div flags */  unsigned int decimals;                            /* Number of decimals in field */}  MYSQL_FIELD;  //列資訊的結構

 

 

typedef struct st_used_mem { /* struct for once_alloc */

  struct st_used_mem *next; /* Next block in use */

  unsigned int left; /* memory left in block  */

  unsigned int size; /* Size of block */

USED_MEM; //記憶體結構

 

typedef struct st_mem_root {

  USED_MEM *free;

  USED_MEM *used;

  USED_MEM *pre_alloc;

  unsigned int min_malloc;

  unsigned int block_size;

  void (*error_handler)(void);

MEM_ROOT;  //記憶體結構

以下是取得資料的相關API:

  1. mysql_store_result()

  MYSQL_RES *mysql_store_result(MYSQL *mysql)

  描述

  對於成功檢索了資料的每個查詢(SELECT、SHOW、DESCRIBE、EXPLAIN、CHECK TABLE等),必須調用mysql_store_result()或mysql_use_result() 。

  對於其他查詢,不需要調用mysql_store_result()或mysql_use_result(),但是如果在任何情況下均調用了mysql_store_result(),它也不會導致任何傷害或效能降低。通過檢查mysql_store_result()是否返回0,可檢測查詢是否沒有結果集(以後會更多)。

  如果希望瞭解查詢是否應返回結果集,可使用mysql_field_count()進行檢查。請參見25.2.3.22節,“mysql_field_count()”。

  mysql_store_result()將查詢的全部結果讀取到用戶端,分配1個MYSQL_RES結構,並將結果置於該結構中。

  如果查詢未返回結果集,mysql_store_result()將返回Null指標(例如,如果查詢是INSERT語句)。

  如果讀取結果集失敗,mysql_store_result()還會返回Null指標。通過檢查mysql_error()是否返回非Null 字元串,mysql_errno()是否返回非0值,或mysql_field_count()是否返回0,可以檢查是否出現了錯誤。

  如果未返回行,將返回空的結果集。(空結果集設定不同於作為傳回值的null 指標)。

  一旦調用了mysql_store_result()並獲得了不是Null指標的結果,可調用mysql_num_rows()來找出結果集中的行數。

  可以調用mysql_fetch_row()來擷取結果集中的行,或調用mysql_row_seek()和mysql_row_tell()來擷取或設定結果集中的當前行位置。

  一旦完成了對結果集的操作,必須調用mysql_free_result()。 

  2. mysql_use_result()

  MYSQL_RES *mysql_use_result(MYSQL *mysql)

  描述

  對於成功檢索資料的每個查詢(SELECT、SHOW、DESCRIBE、EXPLAIN),必須用mysql_store_result()或mysql_use_result()。 

  mysql_use_result()將初始化結果集檢索,但並不像mysql_store_result()那樣將結果集實際讀取到用戶端。它必須通過對mysql_fetch_row()的調用,對每一行分別進行檢索。這將直接從伺服器讀取結果,而不會將其儲存在暫存資料表或本地緩衝區內,與mysql_store_result()相比,速度更快而且使用的記憶體也更少。用戶端僅為當前行和通訊緩衝區分配記憶體,分配的記憶體可增加到max_allowed_packet位元組。 

  另一方面,如果你正在用戶端一側為各行進行大量的處理操作,或者將輸出發送到了使用者可能會鍵入“^S”(停止滾動)的螢幕,就不應使用mysql_use_result()。這會綁定伺服器,並阻止其他線程更新任何錶(資料從這類表獲得)。

  使用mysql_use_result()時,必須執行mysql_fetch_row(),直至返回NULL值,否則,未擷取的行將作為下一個檢索的一部分返回。C API給出命令不同步錯誤,如果忘記了執行該操作,將不能運行該命令。

  不能對結果集用mysql_data_seek()、mysql_row_seek()、mysql_row_tell()、mysql_num_rows()或mysql_affected_rows(),也不應發出其他查詢,直至mysql_use_result()完成為止。(但是,提取了所有行後,mysql_num_rows()將準確返回提取的行數)。

  一旦完成了對結果集的操作,必須調用mysql_free_result()。

 

  傳回值

  MYSQL_RES結果結構。如果出現錯誤,返回NULL。

 

  3.取得一行的資料:

  mysql_fetch_row()

 

  MYSQL_ROW mysql_fetch_row(MYSQL_RES *result)

  描述

  檢索結果集的下一行。在mysql_store_result()之後使用時,如果沒有要檢索的行,mysql_fetch_row()返回NULL。

  在mysql_use_result()之後使用時,如果沒有要檢索的行或出現了錯誤,mysql_fetch_row()返回NULL。

  結果集的列數目由mysql_num_fields(result)給出。如果行中儲存了調用mysql_fetch_row()返回的值,將按照row[0]到row[mysql_num_fields(result)-1],訪問這些值的指標。行中的NULL值由NULL指標指明。

  可以通過調用mysql_fetch_lengths()來獲得行中欄位值的長度。對於空欄位以及包含NULL的欄位,長度為0。通過檢查欄位值的指標,能夠區分它們。如果指標為NULL,欄位為NULL,否則欄位為空白。 

  傳回值

  下一行的MYSQL_ROW結構。如果沒有更多要檢索的行或出現了錯誤,返回NULL。

  範例程式碼:

 

  //假設mysql已經串連好

 

MYSQL_RES* result = mysql_store_result(mysql);

 

if (result  == NULL)

  return;

 

MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
   unsigned long *lengths;
   lengths = mysql_fetch_lengths(result);
   for(i = 0; i < num_fields; i++)
   {
       printf("[%.*s] ", (int) lengths[i], row[i] ? row[i] : "NULL");
   }
   printf("/n");
}

 

 

  4. 取得列的資訊。

  mysql_fetch_field() 

  MYSQL_FIELD *mysql_fetch_field(MYSQL_RES *result)

  描述

  返回採用MYSQL_FIELD結構的結果集的列。重複調用該函數,以檢索關於結果集中所有列的資訊。未剩餘欄位時,mysql_fetch_field()返回NULL。

  每次執行新的SELECT查詢時,將複位mysql_fetch_field(),以返回關於第1個欄位的資訊。調用mysql_field_seek()也會影響mysql_fetch_field()返回的欄位。

  如果調用了mysql_query()以在表上執行SELECT,但未調用mysql_store_result(),如果調用了mysql_fetch_field()以請求BLOB欄位的長度,MySQL將返回預設的Blob長度(8KB)。之所以選擇8KB是因為MySQL不知道BLOB的最大長度。應在日後使其成為可配置的。一旦檢索了結果集,field->max_length將包含特定查詢中該列的最大值的長度。

  傳回值

  當前列的MYSQL_FIELD結構。如果未剩餘任何列,返回NULL。

  錯誤

  無。

  樣本:

MYSQL_FIELD *field; 
while((field = mysql_fetch_field(result)))
{
    printf("field name %s/n", field->name);
}

 

 

 

  5. 同4.

   mysql_fetch_fields()

  MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *result)

  描述

  對於結果集,返回所有MYSQL_FIELD結構的數組。每個結構提供了結果集中1列的欄位定義。

  傳回值

  關於結果集所有列的MYSQL_FIELD結構的數組。

 

  樣本:

unsigned int num_fields;
unsigned int i;
MYSQL_FIELD *fields;
 
num_fields = mysql_num_fields(result);
fields = mysql_fetch_fields(result);
for(i = 0; i < num_fields; i++)
{
   printf("Field %u is %s/n", i, fields[i].name);
}

 

  6. 

  mysql_free_result()

 

  void mysql_free_result(MYSQL_RES *result)

  描述

  釋放由mysql_store_result()、mysql_use_result()、mysql_list_dbs()等為結果集分配的記憶體。完成對結果集的操作後,必須調用mysql_free_result()釋放結果集使用的記憶體。

 

  釋放完成後,不要嘗試訪問結果集。

 

  傳回值

  無。

 

  永遠記得要釋放結果集!!!

 

關於使用MySql出現的記憶體流失問題

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.