设为首页收藏本站

LUPA开源社区

 找回密码
 注册
文章 帖子 博客
LUPA开源社区 首页 业界资讯 技术文摘 查看内容

PHP与MySQL通讯那点事

2013-4-28 14:09| 发布者: 红黑魂| 查看: 3871| 评论: 0|来自: 51CTO

摘要: 在我们的一款WebGame的生产环境中,一次无意的strace抓包时,发现了php与mysql大量通讯的数据。这种情况,在游戏服务器刚启动时,是正常的,但如果是运行一段时间之后,出现大量SELECT的SQL查询,绝对是有问题的,而 ...

继续:

libmysql类库是MYSQL官方提供的类库,每次PHP编译都是指定参数来确定mysql\mysqli\pdo-mysql所使用的连接驱动是哪个。并且,前提你的得先装好mysql的客户端(libmysql类库),以确保有libmysqlclient.so ,

末学抱着试试看的心态,心情沉重的打开了libmysql的源码,终于在Safemalloc.c的line:120附近找到类似libmysqlclient申请内存的代码

  1. //libmysql客户端库Safemalloc.c  line:120  
  2. /* Allocate some memory. */ 
  3.  
  4. void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)  
  5. {  
  6.   ...    
  7.   /*  
  8.     Test for memory limit overrun.  
  9.     If compiled with DBUG, test for error injection. Described in my_sys.h.  
  10.   */ 
  11.   if ((size + sf_malloc_cur_memory > sf_malloc_mem_limit)  
  12.       IF_DBUG(|| my_malloc_error_inject))  
  13.   {  
  14.     IF_DBUG(if (my_malloc_error_inject)  
  15.               errno= ENOMEM;  
  16.             my_malloc_error_inject= 0);  
  17.     irem= 0;  
  18.   }  
  19.   else 
  20.   {  
  21.     /* Allocate the physical memory */ 
  22.     irem= (struct st_irem *) malloc (ALIGN_SIZE(sizeof(struct st_irem)) +  
  23.                      sf_malloc_prehunc +  
  24.                      size + /* size requested */ 
  25.                      4 +    /* overrun mark */ 
  26.                      sf_malloc_endhunc);    //系统的内存分配函数 malloc  
  27.   }  
  28.   ...  
  29.   }  
  30.  
  31.  
  32.  
  33. //下面是mysqlnd驱动的代码,为了省的再弄一个代码高亮的区块,特意放一起了.  
  34. // Mysqlnd客户端库Mysqlnd_alloc.c line:77  
  35. /* {{{ _mysqlnd_emalloc */ 
  36. void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)  
  37. {  
  38. ...  
  39.         ret = _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);    //调用zend的内存分配函数 _emalloc  
  40. ...  
  41.     if (ret && collect_memory_statistics) {  
  42.         *(size_t *) ret = size;  
  43.         MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);  
  44.     }  
  45.     TRACE_ALLOC_RETURN(FAKE_PTR(ret));  
  46. }  
  47. /* }}} */ 

也就是说,libmysql没有调用zend的内分分配函数_emalloc,就没法将内存的使用情况记录到mm_heap结构体中,也就是PHP的memory_get_usage()函数统计不到的原因。好了,虽然末学不是很能读懂源码,但似乎符合问题发生的现象了。

好像,末学又想到一个问题,如果libmysql保存的结果集所占用的内存的话,那么php的配置文件中的memory_limit也就无法限制他的内存使用情况了?也就是说,如果我们很理想的根据系统剩余内存分配了若干个php-fpm进程来启动运行的话,如果发生这情况,将会出现内存不够用的情况,libmysql占用的内存没有被统计到。。。结果是显然的,果然限制不了它。

libmysql与mysqlnd跟memory_limit之间的关系

那mysqlnd可以吗?mysqlnd的内存分配是使用zend的_emalloc函数吗?是的,没错mysqlnd 是我们的大救星。Mysqlnd_alloc.c line:77里代码中,明确看到了。各位SA在编译php时,一定要使用mysqlnd作为php连接mysql server的类库驱动哦。

Mysqlnd的好处可不止这么一点点啊。

内存还是内存:

末学苦于薄弱的英语,冒死翻过GFW,终于在“万恶的资本主义”国家的网站上找到了这些资料,mysqlnd将比libmysql节省将近40%的内存占用哦。如图:

mysqlnd比libmysql节省40%的内存占用

,而且,memory_limit参数可以管的了它哦…


酷毙

雷人
2

鲜花
1

鸡蛋

漂亮

刚表态过的朋友 (3 人)

  • 快毕业了,没工作经验,
    找份工作好难啊?
    赶紧去人才芯片公司磨练吧!!

最新评论

关于LUPA|人才芯片工程|人才招聘|LUPA认证|LUPA教育|LUPA开源社区 ( 浙B2-20090187 浙公网安备 33010602006705号   

返回顶部