[英]Add read replicas for SilverStripe website
首先 - 我很想在此纠正!
只是快速浏览了SilverStripe 3.5站点中的一些ORM类,看起来ORM 确实支持多个数据库连接(请参阅带有参数的DB::get_conn
),它是针对特定用例而设计的。 也就是说,您可能有一个需要写入特定数据库的模块,因此这将允许它。
您想要的是在框架内对此进行原生和自动支持,以便所有读取都转到您的从属设备并写入您的主设备。 不幸的是,它看起来并不像是开箱即用。 您可以通过使用注入器重载几个核心SQL类来实现它。
如果你要尝试它, 这个答案概述了如何将select语句与其余语句分开,并通过不同的数据库连接器运行它们。
作为如何使用SQLSelect
实现此目的的一个简单示例,您会注意到它是可注入的,这意味着您可以轻松地使其超载。
文件:mysite / _config / injector.yml
Injector:
SQLSelect:
class: ReadOnlySQLSelect
您需要使用DB类注册新的数据库连接:
文件:mysite / _config.php
$readDatabaseConfig = array(/** define your DB credentials here, as with the default $databaseConfig **/);
if (!DB::connect($readDatabaseConfig, 'default_read')) {
user_error('Failed to connect to read replica DB!', E_USER_ERROR);
}
现在,重载SQLSelect
类并替换调用DB类方法的部分。 此类继承自SQLExpression
,该类是包含您在此实例中实际关注的方法的类:
文件:mysite / code / ReadOnlySQLSelect.php
class ReadOnlySQLSelect extends SQLSelect
{
public function sql(&$parameters = array())
{
// Changed from SQLExpression: third parameter passed as connection name
$sql = DB::build_sql($this, $parameters, 'default_read');
if (empty($sql)) {
return null;
}
if ($this->replacementsOld) {
$sql = str_replace($this->replacementsOld, $this->replacementsNew, $sql);
}
return $sql;
}
public function execute()
{
$sql = $this->sql($parameters);
// Changed from SQLExpression: skip DB::prepared_query since it doesn't allow
// you to provide the connection name - replace it with its contents instead.
$conn = DB::get_conn('default_read');
return $conn->preparedQuery($sql, $parameters);
}
}
注意: SQLSelect::unlimitedRowCount
技术上应该替换它调用DB::prepared_query
,因为准备好的查询方法调用没有参数的DB::get_conn
,因此将始终返回默认连接。 您可以像上面使用的那样替换DB::prepared_query
行:
$conn = DB::get_conn('default_read');
$result = $conn->preparedQuery($sql, $innerParameters);
如果您实现上述方法,也将new SQLSelect()
更改为SQLSelect::create()
,否则您最终会遇到一些仍然命中主服务器的查询,因为它会因不使用注入器而绕过您的类。
在SQLConditionalExpression
中还有一个实例,您应该替换它( ::toSelect
),但这可能会影响该类的其他子实现的查询转换,如果没有(A)PRing,您将无法做很多事情。修复框架或(B)重载所有其他SQL *类。
此时,您应该拥有将选择查询路由到default_read
连接所需的一切。
在基础结构方面,您应该能够通过RDS控制台设置只读副本。 执行此操作时,它将为您的副本节点提供DNS端点,您可以在_config.php
使用该端点来配置与只读副本数据库的连接。
如果这对您有用,您应该为它创建一个模块并将其放在GitHub上 - 这对将来的其他人肯定会有用!
您还可以考虑向框架发出pull请求,以向DB::prepared_query
等方法添加其他参数以接受连接名称。
另外值得注意的是,如果您正在使用mysqlnd数据库适配器,您可以利用读/写拆分 ,通过某种类型的注入器重载实现,但所有处理都在比应用层更低的级别处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.