php mysql p长连接_PHP中MySQL和Mongodb长连接的实现

MySQL长连接

在使用mysql扩展的时候时代,常听人说mysql长短连接,那么他们之间到底有什么区别呢?百度,google之答案都是千篇一律,都是些简单的介绍,即使有个别试图从源代码上解释,但是仔细分析也是错误的,抱着抛砖引玉的心态,试着重新解释一下其实现原理。

首先在MySQL中连接都是没有分别的,但是在PHP连数据库的时候,却有长连接短连接之分。那么它是怎么实现的呢?

于是查看相关函数实现,PHP里建立长连接的是mysql_pconnect()函数,这个函数和mysql_connet()的内部实现都是一样基于php_mysql_do_connect(),不同的是php_mysql_do_connect()的persistent参数,mysql_pconnet()传递的是1,mysql_connect()是0。

在php_mysql_do_connect()中看到这样几行代码:

zend_rsrc_list_entry *le;

if

(zend_hash_find(&EG(persistent_list),

hashed_details, hashed_details_length 1, (void **)

&le)==FAILURE) {

}

再说EG的作用是取运行时全局变量。persistent_list是PHP内核定义的一个全局hash表,用于存放各种长连接。其定义在Zend\zend_globals.h,Apache进程初始化在main.c里面的php_module_startup()里面通过一系列的调用,最终使用zend_init_rsrc_plist()初始化。

(调用关系是php_module_startup() -> zend_post_startup()

-> executor_globals_ctor() ->

executor_globals_ctor() ->

zend_init_rsrc_plist())

可以看到初始化发生在进程创建的时候。

接下来讲hashed_details,这个hash表的key获取方式有2种分别为正常模式和安全模式,以下第一种是正常模式,第二种是安全模式,应为安全模式不允许有传入的user,passwd等变量,所以直接用了系统user变量。

hashed_details_length =

spprintf(&hashed_details, 0, "mysql_%s_%s_%s_%ld",

SAFE_STRING(host_and_port), SAFE_STRING(user), SAFE_STRING(passwd),

client_flags);

hashed_details_length =

spprintf(&hashed_details, 0, "mysql__%s_",

user);

当创建一个连接成功后,调用以下代码把它添加到persistent_list里面

if

(zend_hash_update(&EG(persistent_list),

hashed_details, hashed_details_length 1, (void *)

&new_le, sizeof(zend_rsrc_list_entry),

NULL)==FAILURE) {

free(mysql);

efree(hashed_details);

MYSQL_DO_CONNECT_RETURN_FALSE();

}

最后讲关闭操作,在mysql_close()里面调用的是zend_list_delete()方法去清理连接资源,但是这个方法只能清理regular_list这个hash表里面的value。所以它不能关闭长连接。

其清理是在进程退出时,在php_module_shutdown()里面调用zend_shuntdown()函数,然后再面调用zend_destroy_rsrc_list()去清理的。

总之persistent_list这个hash表,进程被创建的时候就存在一直到进程退出时的时候才被清理。

通过以上分析基本清楚,PHP里面mysql长链的实现原理。其长连接的有效性是基于进程的!

以后在使用的时候,该怎么考虑呢?

首先mysql在执行语句的时候,不内置ping()功能,所以如果长连接超时了(是的,你没看错,PHP里面mysql长连接会超时,时间参考你用命令行工具连接mysql

server),就会gone away!

其次由于一个进程占用一个或者多个(一个hashed_details占用一个连接)连接而且并不释放,所以你很可能一台web

server占用数百个mysql连接。mysql连接数可能会很快耗尽。

其实persistent_list通常会用来处理各种长连接,也包括mssql,oracle,pgsql等数据库。

Mongodb长连接实现过程

PHP官方的Mongodb扩展里面其实没有长短连接之分,都是长连接。了解MySQL的实现过程,再看mongodb的实现,其实他们原理类似,但实现过程不一样。

通过跟踪mongodb的连接过程(__construct()/connect() ->

php_mongo_connect() ->

mongo_get_read_write_connection() ->

mongo_get_read_write_connection_replicaset() ->

mongo_get_connection_single() ->

mongo_connection_create() ->

mongo_connection_connect())

可以发现,在mongo_get_connection_single()里面会先尝试从hash表里面去取连接。

mongo_manager_connection_find_by_hash(manager,

hash);

找到成功返回,不成功则尝试创建新的连接。成功创建连接后在注册到manager。

mongo_manager_connection_register(manager,

con);

mongodb是通过manager这个全局变量来存储连接的。这个变量是怎么定义的呢,其作用范围有多大。

通过阅读源代码发现在PHP_GINIT_FUNCTION()方法里面初始化了全局的manager,在PHP_GSHUTDOWN_FUNCTION()里面释放了manager。

通过hack发现PHP_GINIT_FUNCTION()在几个INIT_FUNCTION里面,最先被执行,先于PHP_MINIT_FUNCTION()在接受请求之前被初始化,进程退出清理连接。

和MySQL不同的地方,Mongodb的close()可以关闭连接,Mongodb在每次执行查询的时候都会先去ping一下服务存在不存在。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我理解了你的问题。你想知道如何使用 PHP 实现用户注册和登录,但是不使用 MySQL 数据库。那么,我可以给你一些思路和建议,希望能帮助到你。 首先,你需要明确你要使用哪种数据存储方式来保存用户信息。如果不使用 MySQL,可以考虑使用其他的关系型数据库,比如 PostgreSQL、SQLite 等,或者使用非关系型数据库,比如 MongoDB、Redis 等。或者,你也可以考虑使用文件系统来存储用户信息,比如将用户信息保存在 JSON 格式的文件。 其次,你需要设计用户表的结构,包括哪些字段需要保存,比如用户名、密码、邮箱、注册时间等。对于密码,你需要使用加密算法来保证数据安全,比如使用 PHP 的 password_hash() 函数进行加密,使用 password_verify() 函数进行验证。 接下来,你可以编写 PHP 代码来实现用户注册和登录的功能。对于注册功能,你需要编写一个表单页面,用户可以在页面上输入自己的信息,然后将信息提交到 PHP 文件进行处理。在 PHP 文件,你需要将用户输入的信息进行验证和处理,然后将用户信息保存到数据库或文件。 对于登录功能,你也需要编写一个表单页面,用户可以在页面上输入自己的用户名和密码,然后将信息提交到 PHP 文件进行验证。在 PHP 文件,你需要查询数据库或文件,比对用户输入的用户名和密码是否与保存的信息一致,然后根据验证结果进行相应的处理,比如跳转到登录成功页面或提示用户登录失败。 最后,你需要注意安全问题,比如防止 SQL 注入、XSS 攻击等,确保用户信息的安全性和可靠性。 希望这些思路和建议能对你有帮助。如果你有其他问题或疑问,可以继续向我提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值