Yii2 database read-write separation configuration example
To start using the database, you first need to configure the database connection component. This is achieved by adding the db component to the application configuration (the "basic" Web application is config/web.PHP). DSN (Data Source Name) is the data source name, used to specify Database information. As shown below:
return [ // ... 'components' => [ // ... 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=mydatabase', // MySQL, MariaDB //'dsn' => 'sqlite:/path/to/database/file', // SQLite //'dsn' => 'pgsql:host=localhost;port=5432;dbname=mydatabase', // PostgreSQL //'dsn' => 'cubrid:dbname=demodb;host=localhost;port=33000', // CUBRID //'dsn' => 'sqlsrv:Server=localhost;Database=mydatabase', // MS SQL Server, sqlsrv driver //'dsn' => 'dblib:host=localhost;dbname=mydatabase', // MS SQL Server, dblib driver //'dsn' => 'mssql:host=localhost;dbname=mydatabase', // MS SQL Server, mssql driver //'dsn' => 'oci:dbname=//localhost:1521/mydatabase', // Oracle 'username' => 'root', //数据库用户名 'password' => '', //数据库密码 'charset' => 'utf8', ], ], // ... ];
Please refer to the PHP manual for more information about the DSN format. After configuring the connection component, you can use the following syntax to access it:
$connection = \Yii::$app->db;
Please refer to [[yii\db\Connection]] for a list of configurable properties. If you want to connect to the database through ODBC, you need to configure the [[yii\db\Connection::driverName]] attribute, for example:
'db' => [ 'class' => 'yii\db\Connection', 'driverName' => 'mysql', 'dsn' => 'odbc:Driver={MySQL};Server=localhost;Database=test', 'username' => 'root', 'password' => '', ],
Note: If necessary Multiple connection components can be defined when using multiple databases at the same time:
return [ // ... 'components' => [ // ... 'db' => [ 'class' => 'yii\db\Connection', 'dsn' => 'mysql:host=localhost;dbname=mydatabase', 'username' => 'root', 'password' => '', 'charset' => 'utf8', ], 'secondDb' => [ 'class' => 'yii\db\Connection', 'dsn' => 'sqlite:/path/to/database/file', ], ], // ... ];
Used in the code in the following ways:
$primaryConnection = \Yii::$app->db; $secondaryConnection = \Yii::$app->secondDb;
If you don’t want to define the database connection as a global application component, you can initialize it directly in the code:
$connection = new \yii\db\Connection([ 'dsn' => $dsn, 'username' => $username, 'password' => $password, ]); $connection->open();
Tips: If If you need to perform additional SQL queries after creating the connection, you can add the following code to the application configuration file:
return [ // ... 'components' => [ // ... 'db' => [ 'class' => 'yii\db\Connection', // ... 'on afterOpen' => function($event) { $event->sender->createCommand("SET time_zone = 'UTC'")->execute(); } ], ], // ... ];
SQL basic query
Once you have a connection instance, you can execute SQL queries through [[yii\db\Command]].
SELECT query
The query returns multiple rows:
$command = $connection->createCommand('SELECT * FROM post'); $posts = $command->queryAll();
Returns a single row:
$command = $connection->createCommand('SELECT * FROM post WHERE id=1'); $post = $command->queryOne();
Query multi-row single value:
$command = $connection->createCommand('SELECT title FROM post'); $titles = $command->queryColumn();
Query scalar value/calculated value:
$command = $connection->createCommand('SELECT COUNT(*) FROM post'); $postCount = $command->queryScalar();
UPDATE, INSERT, DELETE update, insert and delete, etc.
If executing SQL does not return any data, you can use the execute method in the command:
$command = $connection->createCommand('UPDATE post SET status=1 WHERE id=1'); $command->execute();
You can use the insert, update, delete methods, these methods will generate appropriate SQL based on the parameters and execute it.
// INSERT $connection->createCommand()->insert('user', [ 'name' => 'Sam', 'age' => 30, ])->execute(); // INSERT 一次插入多行 $connection->createCommand()->batchInsert('user', ['name', 'age'], [ ['Tom', 30], ['Jane', 20], ['Linda', 25], ])->execute(); // UPDATE $connection->createCommand()->update('user', ['status' => 1], 'age > 30')->execute(); // DELETE $connection->createCommand()->delete('user', 'status = 0')->execute();
Referenced table and column names
Most of the time table and column names are referenced safely using the following syntax:
$sql = "SELECT COUNT([[$column]]) FROM {{table}}"; $rowCount = $connection->createCommand($sql)->queryScalar();
The above code [[$column]] will be converted to reference the appropriate column name, and {{table}} will be converted to reference the appropriate table name. The table name has a special variable {{%Y}}. If a table prefix is set, use this variant to automatically add a prefix before the table name:
$sql = "SELECT COUNT([[$column]]) FROM {{%$table}}"; $rowCount = $connection->createCommand($sql)->queryScalar();
If the table prefix is set in the configuration file as follows, the above code will query the results in the tbl_table table:
return [ // ... 'components' => [ // ... 'db' => [ // ... 'tablePrefix' => 'tbl_', ], ], ];
Another option to manually reference the table name and column name is Use [[yii\db\Connection::quoteTableName()]] and [[yii\db\Connection::quoteColumnName()]]:
$column = $connection->quoteColumnName($column); $table = $connection->quoteTableName($table); $sql = "SELECT COUNT($column) FROM $table"; $rowCount = $connection->createCommand($sql)->queryScalar();
Preprocessing statements
To safely pass query parameters, you can use preprocessing statements. First, you should use: placeholder placeholder, and then bind the variable to the corresponding placeholder:
$command = $connection->createCommand('SELECT * FROM post WHERE id=:id'); $command->bindValue(':id', $_GET['id']); $post = $command->query();
Another usage is to prepare a prepared statement once and execute multiple queries:
$command = $connection->createCommand('DELETE FROM post WHERE id=:id'); $command->bindParam(':id', $id); $id = 1; $command->execute(); $id = 2; $command->execute();
Tip , it is more efficient to bind variables before execution, and then change the value of the variable in each execution (generally used in loops).
Transaction
When you need to execute multiple related queries sequentially, you can encapsulate them into a transaction to protect data consistency. Yii provides a simple interface to implement transaction operations. Execute the SQL transaction query statement as follows:
$transaction = $connection->beginTransaction(); try { $connection->createCommand($sql1)->execute(); $connection->createCommand($sql2)->execute(); // ... 执行其他 SQL 语句 ... $transaction->commit(); } catch(Exception $e) { $transaction->rollBack(); }
We start a transaction through [[yii\db\Connection::beginTransaction()|beginTransaction()]] and catch the exception through try catch. When the execution is successful, Submit and end the transaction through [[yii\db\Transaction::commit()|commit()]]. When an exception occurs and fails, use [[yii\db\Transaction::rollBack()|rollBack()]] to perform transaction rollback. Roll.
You can also nest multiple transactions if necessary:
// 外部事务 $transaction1 = $connection->beginTransaction(); try { $connection->createCommand($sql1)->execute(); // 内部事务 $transaction2 = $connection->beginTransaction(); try { $connection->createCommand($sql2)->execute(); $transaction2->commit(); } catch (Exception $e) { $transaction2->rollBack(); } $transaction1->commit(); } catch (Exception $e) { $transaction1->rollBack(); }
Note that the database you use must support Savepoints to execute correctly. The above code can be executed in all relational data, but security can only be guaranteed if Savepoints are supported.
Yii also supports setting isolation levels for transactions. When executing a transaction, the default isolation level of the database will be used. You can also specify the isolation level for things. Yii provides the following constants as commonly used isolation levels Level
[[\yii\db\Transaction::READ_UNCOMMITTED]] - Allows reading changed uncommitted data, which may lead to dirty reads, non-repeatable reads and phantom reads
[[\yii\db\Transaction::READ_COMMITTED]] - Allow concurrent transactions to be read after they are committed, which can avoid dirty reads, which may lead to repeated reads and phantom reads.
[[\yii\db\Transaction::REPEATABLE_READ]] - Multiple reads of the same field have consistent results, which can lead to phantom reads.
[[\yii\db\Transaction::SERIALIZABLE]] - Completely obeys the ACID principle to ensure that dirty reads, non-repeatable reads and phantom reads do not occur.
You can use the above constants or use a string command and execute the command in the corresponding database to set the isolation level. For example, the valid command for postgres is SERIALIZABLE READ ONLY DEFERRABLE.
注意:某些数据库只能针对连接来设置事务隔离级别,所以你必须要为连接明确制定隔离级别.目前受影响的数据库:MSSQL SQLite
注意:SQLite 只支持两种事务隔离级别,所以你只能设置READ UNCOMMITTED 和 SERIALIZABLE.使用其他隔离级别会抛出异常.
注意:PostgreSQL 不允许在事务开始前设置隔离级别,所以你不能在事务开始时指定隔离级别.你可以在事务开始之后调用[[yii\db\Transaction::setIsolationLevel()]] 来设置.
数据库复制和读写分离
很多数据库支持数据库复制 database replication来提高可用性和响应速度. 在数据库复制中,数据总是从主服务器 到 从服务器. 所有的插入和更新等写操作在主服务器执行,而读操作在从服务器执行.
通过配置[[yii\db\Connection]]可以实现数据库复制和读写分离.
[ 'class' => 'yii\db\Connection', // 配置主服务器 'dsn' => 'dsn for master server', 'username' => 'master', 'password' => '', // 配置从服务器 'slaveConfig' => [ 'username' => 'slave', 'password' => '', 'attributes' => [ // use a smaller connection timeout PDO::ATTR_TIMEOUT => 10, ], ], // 配置从服务器组 'slaves' => [ ['dsn' => 'dsn for slave server 1'], ['dsn' => 'dsn for slave server 2'], ['dsn' => 'dsn for slave server 3'], ['dsn' => 'dsn for slave server 4'], ], ]
以上的配置实现了一主多从的结构,从服务器用以执行读查询,主服务器执行写入查询,读写分离的功能由后台代码自动完成.调用者无须关心.例如:
// 使用以上配置创建数据库连接对象 $db = Yii::createObject($config); // 通过从服务器执行查询操作 $rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll(); // 通过主服务器执行更新操作 $db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute();
注意:通过[[yii\db\Command::execute()]] 执行的查询被认为是写操作,所有使用[[yii\db\Command]]来执行的其他查询方法被认为是读操作.你可以通过$db->slave得到当前正在使用能够的从服务器.
Connection组件支持从服务器的负载均衡和故障转移,当第一次执行读查询时,会随即选择一个从服务器进行连接,如果连接失败则又选择另一个,如果所有从服务器都不可用,则会连接主服务器。你可以配置[[yii\db\Connection::serverStatusCache|server status cache]]来记住那些不能连接的从服务器,使Yii 在一段时间[[yii\db\Connection::serverRetryInterval].内不会重复尝试连接那些根本不可用的从服务器.
注意:在上述配置中,每个从服务器连接超时时间被指定为10s. 如果在10s内不能连接,则被认为该服务器已经挂掉.你也可以自定义超时参数.
你也可以配置多主多从的结构,例如:
[ 'class' => 'yii\db\Connection', // 配置主服务器 'masterConfig' => [ 'username' => 'master', 'password' => '', 'attributes' => [ // use a smaller connection timeout PDO::ATTR_TIMEOUT => 10, ], ], // 配置主服务器组 'masters' => [ ['dsn' => 'dsn for master server 1'], ['dsn' => 'dsn for master server 2'], ], // 配置从服务器 'slaveConfig' => [ 'username' => 'slave', 'password' => '', 'attributes' => [ // use a smaller connection timeout PDO::ATTR_TIMEOUT => 10, ], ], // 配置从服务器组 'slaves' => [ ['dsn' => 'dsn for slave server 1'], ['dsn' => 'dsn for slave server 2'], ['dsn' => 'dsn for slave server 3'], ['dsn' => 'dsn for slave server 4'], ], ]
上述配置制定了2个主服务器和4个从服务器.Connection组件也支持主服务器的负载均衡和故障转移,与从服务器不同的是,如果所有主服务器都不可用,则会抛出异常.
注意:当你使用[[yii\db\Connection::masters|masters]]来配置一个或多个主服务器时,Connection中关于数据库连接的其他属性(例如:dsn, username, password)都会被忽略.
事务默认使用主服务器的连接,并且在事务执行中的所有操作都会使用主服务器的连接,例如:
// 在主服务器连接上开始事务 $transaction = $db->beginTransaction(); try { // 所有的查询都在主服务器上执行 $rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll(); $db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute(); $transaction->commit(); } catch(\Exception $e) { $transaction->rollBack(); throw $e; }
如果你想在从服务器上执行事务操作则必须要明确地指定,比如:
$transaction = $db->slave->beginTransaction();
有时你想强制使用主服务器来执行读查询,你可以调用seMaster()方法.
$rows = $db->useMaster(function ($db) { return $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll(); });
你也可以设置$db->enableSlaves 为false来使所有查询都在主服务器上执行.
操作数据库模式
获得模式信息
你可以通过 [[yii\db\Schema]]实例来获取Schema信息:
$schema = $connection->getSchema();
该实例包括一系列方法来检索数据库多方面的信息:
$tables = $schema->getTableNames();
更多信息请参考[[yii\db\Schema]]
修改模式
除了基础的 SQL 查询,[[yii\db\Command]]还包括一系列方法来修改数据库模式:
创建/重命名/删除/清空表
增加/重命名/删除/修改字段
增加/删除主键
增加/删除外键
创建/删除索引
使用示例:
// 创建表 $connection->createCommand()->createTable('post', [ 'id' => 'pk', 'title' => 'string', 'text' => 'text', ]);
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。
更多yii2 数据库读写分离配置示例相关文章请关注PHP中文网!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Alipay PHP...

JWT is an open standard based on JSON, used to securely transmit information between parties, mainly for identity authentication and information exchange. 1. JWT consists of three parts: Header, Payload and Signature. 2. The working principle of JWT includes three steps: generating JWT, verifying JWT and parsing Payload. 3. When using JWT for authentication in PHP, JWT can be generated and verified, and user role and permission information can be included in advanced usage. 4. Common errors include signature verification failure, token expiration, and payload oversized. Debugging skills include using debugging tools and logging. 5. Performance optimization and best practices include using appropriate signature algorithms, setting validity periods reasonably,

Session hijacking can be achieved through the following steps: 1. Obtain the session ID, 2. Use the session ID, 3. Keep the session active. The methods to prevent session hijacking in PHP include: 1. Use the session_regenerate_id() function to regenerate the session ID, 2. Store session data through the database, 3. Ensure that all session data is transmitted through HTTPS.

How to debug CLI mode in PHPStorm? When developing with PHPStorm, sometimes we need to debug PHP in command line interface (CLI) mode...

The application of SOLID principle in PHP development includes: 1. Single responsibility principle (SRP): Each class is responsible for only one function. 2. Open and close principle (OCP): Changes are achieved through extension rather than modification. 3. Lisch's Substitution Principle (LSP): Subclasses can replace base classes without affecting program accuracy. 4. Interface isolation principle (ISP): Use fine-grained interfaces to avoid dependencies and unused methods. 5. Dependency inversion principle (DIP): High and low-level modules rely on abstraction and are implemented through dependency injection.

How to automatically set the permissions of unixsocket after the system restarts. Every time the system restarts, we need to execute the following command to modify the permissions of unixsocket: sudo...

Static binding (static::) implements late static binding (LSB) in PHP, allowing calling classes to be referenced in static contexts rather than defining classes. 1) The parsing process is performed at runtime, 2) Look up the call class in the inheritance relationship, 3) It may bring performance overhead.

Sending JSON data using PHP's cURL library In PHP development, it is often necessary to interact with external APIs. One of the common ways is to use cURL library to send POST�...
