MongoDB PHP Driver的连接处理 1.3版本的PHP MongoDB driver重写了连接处理库,和以前版本相比,在持久连接和连接池方面,都有了重大的变化。 1.2版本的连接管理 1.2版本的驱动引入了连接池,在执行任何查询时,都会从连接池中请求一个连接,完成之后再归还
MongoDB PHP Driver的连接处理
1.3版本的PHP MongoDB driver重写了连接处理库,和以前版本相比,在持久连接和连接池方面,都有了重大的变化。
1.2版本的连接管理
1.2版本的驱动引入了连接池,在执行任何查询时,都会从连接池中请求一个连接,完成之后再归还给连接池。这里的完成是指持有该连接的变量离开了它的作用域,下面是一个示例。
最简单的版本:
<?php $m = new MongoClient(); // ← 从连接池请求连接 $c = $m->demo->test; $c->insert( array( 'test' => 'yes' ) ); ?>
← $m离开作用域,连接归还给连接池
在函数中:
<?php function doQuery() { $m = new MongoClient(); // ← 从连接池请求连接 $c = $m->demo->test; $c->insert( array( 'test' => 'yes' ) ); } // ← $m离开作用域,连接归还给连接池 ?>
在某些情况下,系统可能会产生大量的连接,比如在ORMs/ODMs的某个复杂结构中引用连接对象,如下例子:
<?php for ( $i = 0; $i < 5; $i++ ) { $conns[] = new MongoClient(); }// ← 现在有5个连接 ?>
1.3版本的连接管理
在1.3版本中,连接管理做了很大改动。每个worker进程(线程、PHP-FPM或Apache worker)中,驱动把连接管理和Mongo*对象分离,降低驱动的复杂度。下面以单个节点的MongoDB实例来说明驱动如何处理连接。
当一个worker进程启动,MongoDB驱动会为之初始化连接管理器管理连接,并且默认没有连接。
在第一个请求调用new MongoClient();时,驱动创建一个新连接,并且以一个哈希值标识这个连接。这个哈希值包括以下参数:主机名、端口,进程ID和可选的replica set名,如果是密码验证的连接,则还包括数据库名、用户名和密码的哈希值(对于密码验证的连接,我们后面再详细讨论)。调用MongoClient::getConnections()方法,可以查看连接对应的哈希值:
<?php $m = new MongoClient( 'mongodb://whisky:27017/' ); var_dump( $m->getConnections()[0]['hash'] ); ?>
输出:
string(22) "whisky:27017;-;X;22835"
输出中的"-"表示该连接不属于某个replica set,"X"是没有用户名、数据库和密码时的占位符,22835是当前进程的进程ID。
然后该连接会在连接管理器中注册:
在需要连接的任何时候,包括插入、删除、更新、查找或执行命令,驱动都会向管理器请求一个合适的连接来执行。请求连接时会用到new MongoClient()的参数和当前进程的ID。每个worker进程/线程,连接管理器都会有一个连接列表,而每个PHP worker同一时刻,只会运行一个请求,因此和每个MongoDB之间只需要一个连接,不断重用,直到PHP worker终止或显式调用MongoClient::close()关闭连接。
Replica sets
在存在复制集的环境中,情形有点不一样。new MongoClient()的连接字符串中,需要指定多个hosts,并标示当前正在实用复制集:
$m = new MongoClient("mongodb://whisky:13000,whisky:13001/?replicaSet=seta");
其中的replicaSet参数不能省略,否则驱动会认为你是准备连接三个不同的mongos进程。
在实例化时,驱动会检查复制集的拓扑结构。下面例子的输出,显示在调用new MongoClient()之后,复制集中所有可见的数据节点都会在管理器中注册一个连接:
<?php $m = new MongoClient( 'mongodb://whisky:13001/?replicaSet=seta' ); foreach ( $m->getConnections() as $c ) { echo $c['hash'], "\n"; } ?>
输出:
whisky:13001;seta;X;32315 whisky:13000;seta;X;32315
虽然连接字符串中没有whisky:13000节点,但是管理器中已经注册了两个连接:
管理器不仅包含连接的哈希值和TCP/IP socket,还保存哪个节点是主节点,以及每个节点的“距离"。下面的脚本显示了这些额外的信息;
<?php $m = new MongoClient( 'mongodb://whisky:13001/?replicaSet=seta' ); foreach ( $m->getConnections() as $c ) { echo $c['hash'], ":\n", " - {$c['connection']['connection_type_desc']}, ", "{$c['connection']['ping_ms']} ms\n"; } ?>
输出:
whisky:13001;seta;X;5776: - SECONDARY, 1 ms whisky:13000;seta;X;5776: - PRIMARY, 0 ms
驱动把操作分为两种类型:写操作,包括插入、更新、删除和命令;读操作,包括find和findOne。默认情况下,如果没有设置读偏好参数,管理器会一直返回主节点的连接。读偏好参数可以通过setSlaveOkay()设置,也可以在连接字符串中设置:
$m = new MongoClient("mongodb://whisky:13000,whisky:13001/?replicaSet=seta&readPreference=secondaryPreferred");
加上这些参数后,连接字符串变得特别长,因此PHP驱动允许将选项放在数组中,作为第二个参数传入:
$options = array( 'replicaSet' => 'seta', 'readPreference' => 'secondaryPreferred', ); $m = new MongoClient("mongodb://whisky:13000,whisky:13001/", $options);
对于每个操作,驱动向管理器请求获取一个合适的连接。对于写操作,会一直返回主节点的连接;对于读操作,如果辅助节点可用且“距离”不远的话,则会返回该辅助节点的连接。
验证的连接
如果MongoDB启用验证功能,那么连接的哈希值会包含验证相关的哈希值。这样不同脚本,使用不同的用户名、密码连接同一个MongoDB上的不同的数据库时,能够相互区分,而不会误用连接。下面示例使用admin用户名连接admin数据库,然后观察hash值的变化:
<?php $m = new MongoClient( 'mongodb://admin:admin@whisky:27017/admin' ); var_dump( $m->getConnections()[0]['hash'] ); ?>
输出:
string(64) "whisky:27017;-;admin/admin/bda5cc70cd5c23f7ffa1fda978ecbd30;8697"
以前示例中的"X"部分已经替换为一个包含数据库名admin、用户名admin和哈希值bda5cc70cd5c23f7ffa1fda978ecbd30,该哈希值是根据用户名、数据库名和密码哈希值计算得来。
为了验证能够正确工作,需要在连接字符串中包含数据库名,否则会默认为admin。
在建立连接后要使用数据库,需要先选择该数据库,如:
$collection = $m->demoDb->collection; $collection->findOne();
如果选择的数据库是连接字符串中指定的数据库,或者连接字符串中的数据库是admin,那么一切都会正常运行。否则,驱动会创建一个新的连接,从而防止验证被绕过,如下所示:
<?php $m = new MongoClient( 'mongodb://user:user@whisky:27017/test' ); $db = $m->test2; $collection = $db->collection; var_dump( $collection->findOne() ); ?>
输出:
Fatal error: Uncaught exception 'MongoCursorException' with message 'whisky:27017: unauthorized db:test2 ns:test2.collection lock type:0 client:127.0.0.1' in …/mongo-connect-5.php.txt:6
因为我们的连接并没有执行test2数据库的授权验证,因而失败。如果我们执行验证,就会正常运行:
<?php $m = new MongoClient( 'mongodb://user:user@whisky:27017/test' ); $db = $m->test2; $db->authenticate('user2', 'user2' ); $collection = $db->collection; $collection->findOne(); foreach ( $m->getConnections() as $c ) { echo $c['hash'], "\n"; } ?>
输出:
whisky:27017;-;test/user/602b672e2fdcda7b58a042aeeb034376;26983 whisky:27017;-;test2/user2/984b6b4fd6c33f49b73f026f8b47c0de;26983
现在管理器中有两个已验证的连接:
顺便提一句,如果你打开了E_DEPRECATED级别的错误提示,则会看到:
Deprecated: Function MongoDB::authenticate() is deprecated in …/mongo-connect-6.php.txt on line 5
驱动建议通过创建两个MongoClient对象完成该类任务:
<?php $mTest1 = new MongoClient( 'mongodb://user:user@whisky:27017/test', array( 'connect' => false ) ); $mTest2 = new MongoClient( 'mongodb://user2:user2@whisky:27017/test2', array( 'connect' => false ) ); $mTest1->test->test->findOne(); $mTest2->test2->test->findOne(); foreach ( $mTest2->getConnections() as $c ) { echo $c['hash'], "\n"; } ?>
单个MongoDB服务器能支持的并发连接相当有限,如果使用PHP-FPM的话,每个worker进程有自己独立的连接池,那么很容易达到连接数的上限。因此,在生产环境中,不管有没有使用复制集,都要部署mongos,然后PHP-FPM连接mongos,这样可以减少mongod的连接数,并且PHP-FPM和mongos之间可以使用短连接(即每个请求结束时都显式调用close函数关闭MongoDB连接)。
原文链接:http://derickrethans.nl/mongodb-connection-handling.html
原文地址:MongoDB PHP Driver的连接处理, 感谢原作者分享。

MySQL是一種開源的關係型數據庫管理系統,主要用於快速、可靠地存儲和檢索數據。其工作原理包括客戶端請求、查詢解析、執行查詢和返回結果。使用示例包括創建表、插入和查詢數據,以及高級功能如JOIN操作。常見錯誤涉及SQL語法、數據類型和權限問題,優化建議包括使用索引、優化查詢和分錶分區。

MySQL是一個開源的關係型數據庫管理系統,適用於數據存儲、管理、查詢和安全。 1.它支持多種操作系統,廣泛應用於Web應用等領域。 2.通過客戶端-服務器架構和不同存儲引擎,MySQL高效處理數據。 3.基本用法包括創建數據庫和表,插入、查詢和更新數據。 4.高級用法涉及復雜查詢和存儲過程。 5.常見錯誤可通過EXPLAIN語句調試。 6.性能優化包括合理使用索引和優化查詢語句。

選擇MySQL的原因是其性能、可靠性、易用性和社區支持。 1.MySQL提供高效的數據存儲和檢索功能,支持多種數據類型和高級查詢操作。 2.採用客戶端-服務器架構和多種存儲引擎,支持事務和查詢優化。 3.易於使用,支持多種操作系統和編程語言。 4.擁有強大的社區支持,提供豐富的資源和解決方案。

InnoDB的鎖機制包括共享鎖、排他鎖、意向鎖、記錄鎖、間隙鎖和下一個鍵鎖。 1.共享鎖允許事務讀取數據而不阻止其他事務讀取。 2.排他鎖阻止其他事務讀取和修改數據。 3.意向鎖優化鎖效率。 4.記錄鎖鎖定索引記錄。 5.間隙鎖鎖定索引記錄間隙。 6.下一個鍵鎖是記錄鎖和間隙鎖的組合,確保數據一致性。

MySQL查询性能不佳的原因主要包括没有使用索引、查询优化器选择错误的执行计划、表设计不合理、数据量过大和锁竞争。1.没有索引导致查询缓慢,添加索引后可显著提升性能。2.使用EXPLAIN命令可以分析查询计划,找出优化器错误。3.重构表结构和优化JOIN条件可改善表设计问题。4.数据量大时,采用分区和分表策略。5.高并发环境下,优化事务和锁策略可减少锁竞争。

在數據庫優化中,應根據查詢需求選擇索引策略:1.當查詢涉及多個列且條件順序固定時,使用複合索引;2.當查詢涉及多個列但條件順序不固定時,使用多個單列索引。複合索引適用於優化多列查詢,單列索引則適合單列查詢。

要優化MySQL慢查詢,需使用slowquerylog和performance_schema:1.啟用slowquerylog並設置閾值,記錄慢查詢;2.利用performance_schema分析查詢執行細節,找出性能瓶頸並優化。

MySQL和SQL是開發者必備技能。 1.MySQL是開源的關係型數據庫管理系統,SQL是用於管理和操作數據庫的標準語言。 2.MySQL通過高效的數據存儲和檢索功能支持多種存儲引擎,SQL通過簡單語句完成複雜數據操作。 3.使用示例包括基本查詢和高級查詢,如按條件過濾和排序。 4.常見錯誤包括語法錯誤和性能問題,可通過檢查SQL語句和使用EXPLAIN命令優化。 5.性能優化技巧包括使用索引、避免全表掃描、優化JOIN操作和提升代碼可讀性。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

EditPlus 中文破解版
體積小,語法高亮,不支援程式碼提示功能

記事本++7.3.1
好用且免費的程式碼編輯器

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器