设为首页 加入收藏

TOP

php与mysql通讯那点事(三)
2014-11-24 07:55:32 来源: 作者: 【 】 浏览:2
Tags:php mysql 通讯 那点事
ath=/services/php/etc' '--with-pdo-mysql=mysqlnd' '--with-mysql=mysqlnd' '--with-mysqli=mysqlnd' '--enable-bcmath' '--enable-fpm
有点乱:

mysql、mysqli、pdo-mysql、libmysql、mysqlnd 好多名词,有点乱,没关系,一张图让你清晰起来:

mysql、mysqli、pdo-mysql、libmysql、mysqlnd之间关系

mysql、mysqli、pdo-mysql、libmysql、mysqlnd之间关系


mysqlnd跟libmysql一样,都是直接与mysql server通讯的驱动类库。 而php程序员使用的mysql、mysqli、pdo-mysql是面向程序员调用的API接口。。

继续:

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

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



//libmysql客户端库Safemalloc.c  line:120
/* Allocate some memory. */

void *_mymalloc(size_t size, const char *filename, uint lineno, myf MyFlags)
{
  ...  
  /*
    Test for memory limit overrun.
    If compiled with DBUG, test for error injection. Described in my_sys.h.
  */
  if ((size + sf_malloc_cur_memory > sf_malloc_mem_limit)
      IF_DBUG(|| my_malloc_error_inject))
  {
    IF_DBUG(if (my_malloc_error_inject)
              errno= ENOMEM;
            my_malloc_error_inject= 0);
    irem= 0;
  }
  else
  {
    /* Allocate the physical memory */
    irem= (struct st_irem *) malloc (ALIGN_SIZE(sizeof(struct st_irem)) +
				     sf_malloc_prehunc +
				     size +	/* size requested */
				     4 +	/* overrun mark */
				     sf_malloc_endhunc);    //系统的内存分配函数 malloc
  }
  ...
  }



//下面是mysqlnd驱动的代码,为了省的再弄一个代码高亮的区块,特意放一起了.
// Mysqlnd客户端库Mysqlnd_alloc.c line:77
/* {{{ _mysqlnd_emalloc */
void * _mysqlnd_emalloc(size_t size MYSQLND_MEM_D)
{
...
		ret = _emalloc(REAL_SIZE(size) ZEND_FILE_LINE_CC ZEND_FILE_LINE_ORIG_RELAY_CC);    //调用zend的内存分配函数 _emalloc
...
	if (ret && collect_memory_statistics) {
		*(size_t *) ret = size;
		MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(STAT_MEM_EMALLOC_COUNT, 1, STAT_MEM_EMALLOC_AMOUNT, size);
	}
	TRACE_ALLOC_RETURN(FAKE_PTR(ret));
}
/* }}} */

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

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

libmysql与mysqlnd跟memory_limit之间的关系

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%的内存占用

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

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

速度,速度:
国外友人给了一份测试结果,比较的API是mysql\mysqli,比较的驱动是libmysql\mysqlnd

  • 使用mysqlnd驱动的ext\mysqli接口速度最快
  • 使用libmysql驱动的ext\mysqli接口慢了6%
  • 使用libmysql驱动的ext\mysql接口慢了3%

并且给出了mysqli在两个驱动下的执行时间:

mysqli_select_varchar_buffered

mysqli_select_varchar_buffered

还有,还有哦…
mysqlnd还支持各种debug调试哦,各种strace跟踪哦…还支持….算了,你自己下载mysqlnd相比libmysql的优点看吧。末学可是搜了很久才搜到这个ppt。

推荐:

1,再推荐一片关于mysqlnd持久链接的文章:PHP 5.3: Persistent Connections with ext/mysqli

2,你的应用的cache的存储是程序员自己根据DB数据结果,查询条件,hash取值,存到memcache中的吗?想不想尝试下自动实现的?mysqlnd的插件可以尝试下:PHP: Client side caching for all MySQL extensions ,支持memcached,apc,sqlit哦。

回到开始:
有人说,当php调用mysql_query时,mysql server会返回本次查询的结果到php所在服务器的缓冲区中。当程序调用mysql_fetch_assoc/mysql_fetch_ro

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇Windows Server2008下MYSQL外网无.. 下一篇sqlite加载CSV文件

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·Python爬虫教程(从 (2025-12-26 16:49:14)
·【全269集】B站最详 (2025-12-26 16:49:11)
·Python爬虫详解:原 (2025-12-26 16:49:09)
·Spring Boot Java: (2025-12-26 16:20:19)
·Spring BootでHello (2025-12-26 16:20:15)