我有24个数据库,其中有一个标有email_queue
的表格。
我有另一个数据库,其中包含所有包含email_queue
表的数据库的列表。
我遍历数据库列表并查询我的email_queue
表以发送每个数据库的邮件。
这个问题是,php脚本在第三个数据库被阻止,发送500封电子邮件,而其他数据库在那之后等待轮到他们。
我试图找出如何同时查询所有24个数据库并同时发送电子邮件队列。
有什么建议吗?
答案 0 :(得分:4)
我认为拥有这么多数据库可能是糟糕设计的标志。如果你不能改变它并且现在需要继续前进,我建议选择以下两个选项之一:
这是一个使用mysqli扩展(需要mysqlnd驱动程序)的完整示例:
$credentials = array(
array(
'host' => 'host1',
'user' => 'user',
'password' => 'password',
'database' => 'database'
),
array(
'host' => 'host2',
'user' => 'user',
'password' => 'password',
'database' => 'database'
),
// credentials for other sites
);
$dbcs = array();
foreach ($credentials as $config) {
$dbcs[] = array($db = new mysqli(
$config['host'],
$config['user'],
$config['pass'],
$config['database']
));
$query = ""; // here is your query to do whatever it is with your table
$db->query($query, MYSQLI_ASYNC);
}
$results = array();
$errors = array();
$rejected = array();
$secondsToWait = 1;
while (!empty($dbcs)) {
foreach ($dbcs as $key => $c) {
$db = $c[0];
if (mysqli_poll($c, $errors, $rejected, $secondsToWait) == 1) {
$r = $db->reap_async_query();
// here you would do your fetches for each query, such as
$results[] = $r->fetch_assoc();
// do what you need to do with the result
// then cleanup
$r->free();
$db->close();
unset($dbcs[$key]);
}
}
}
请注意,它确实有缺点,例如查询失败可能会导致整个程序崩溃。
答案 1 :(得分:2)
使用curl_multi_open
进行此操作将你的脚本拆分为两个,你可以制作一个php文件(比如email_out.php)获取数据库名称(或者用于查找数据库名称的一些变量,交换机将在for循环中或者在email_out中.php),然后根据那个脚本做大量邮件。
第二部分使用curl_multi_open多次打开email_out.php脚本,有效地创建了与不同数据库的多个独立连接,这些脚本可以在不同的时间解析,因为它们都是并行运行的。 从本质上讲,你的循环现在使用不同的参数多次将curl_multi_open添加到脚本中,然后异步执行所有这些脚本。
class Fork
{
private $_handles = array();
private $_mh = array();
function __construct()
{
$this->_mh = curl_multi_init();
}
function add($url)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_multi_add_handle($this->_mh, $ch);
$this->_handles[] = $ch;
return $this;
}
function run()
{
$running=null;
do {
curl_multi_exec($this->_mh, $running);
usleep (250000);
} while ($running > 0);
for($i=0; $i < count($this->_handles); $i++) {
$out = curl_multi_getcontent($this->_handles[$i]);
$data[$i] = json_decode($out);
curl_multi_remove_handle($this->_mh, $this->_handles[$i]);
}
curl_multi_close($this->_mh);
return $data;
}
}
(来自http://gonzalo123.com/2010/10/11/speed-up-php-scripts-with-asynchronous-database-queries/)
所以你的循环看起来像这样:
$fork = new Fork;
for ($i = 0; $i < 24; $i++) {
$fork->add("email_out.php?t=" . $i);
}
$fork->run();
答案 2 :(得分:0)
在你的脚本中试试这个。
set_time_limit(0);
覆盖PHP的max_execution_time getopt()
函数从命令行运行脚本时获取数据库名称(即php script.php -d database1
)。-d
)发送电子邮件的数据库创建一个条目。如果您有20个数据库,那么您必须有20个条目。使用这种方式,您将看到每个cron作业的单独PHP进程,如果您遇到错误,可以隔离数据库。