Beispiel für die Konfiguration der Lese-/Schreibtrennung der Yii2-Datenbank

高洛峰
Freigeben: 2023-03-05 18:44:02
Original
1175 Leute haben es durchsucht

Um mit der Nutzung der Datenbank zu beginnen, müssen Sie zunächst die Datenbankverbindungskomponente konfigurieren. Dies wird durch Hinzufügen der Datenbankkomponente zur Anwendungskonfiguration erreicht (die „grundlegende“ Webanwendung ist config/web.PHP (Datenquelle). Name) ist der Name der Datenquelle, der zur Angabe der Datenbankinformationen verwendet wird:

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',
    ],
  ],
  // ...
];
Nach dem Login kopieren

Weitere Informationen dazu finden Sie im PHP-Handbuch DSN-Format. Nach der Konfiguration der Verbindungskomponente kann mit der folgenden Syntax darauf zugegriffen werden:

$connection = \Yii::$app->db;
Nach dem Login kopieren

Eine Liste der konfigurierbaren Eigenschaften finden Sie unter [[yiidbConnection]]. . Wenn Sie über ODBC eine Verbindung zur Datenbank herstellen möchten, müssen Sie das Attribut [[yiidbConnection::driverName]] konfigurieren, zum Beispiel:

'db' => [
  'class' => 'yii\db\Connection',
  'driverName' => 'mysql',
  'dsn' => 'odbc:Driver={MySQL};Server=localhost;Database=test',
  'username' => 'root',
  'password' => '',
],
Nach dem Login kopieren

Hinweis: Wenn Sie sie gleichzeitig verwenden müssen, können mehrere Verbindungskomponenten für mehrere Datenbanken definiert werden:

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', 
    ],
  ],
  // ...
];
Nach dem Login kopieren

wird im Code in verwendet Folgende Möglichkeiten:

$primaryConnection = \Yii::$app->db;
$secondaryConnection = \Yii::$app->secondDb;
Nach dem Login kopieren

Wenn Sie die Datenbankverbindung nicht als globale Anwendungskomponente definieren möchten, können Sie sie direkt im Code initialisieren:

$connection = new \yii\db\Connection([
  'dsn' => $dsn,
   'username' => $username,
   'password' => $password,
]);
$connection->open();
Nach dem Login kopieren

Kleiner Tipp: Wenn Sie nach dem Erstellen der Verbindung zusätzliche SQL-Abfragen durchführen müssen, können Sie der Anwendungskonfigurationsdatei den folgenden Code hinzufügen:

return [
  // ...
  'components' => [
    // ...
    'db' => [
      'class' => 'yii\db\Connection',
      // ...
      'on afterOpen' => function($event) {
        $event->sender->createCommand("SET time_zone = 'UTC'")->execute();
      }
    ],
  ],
  // ...
];
Nach dem Login kopieren

SQL-Basisabfrage

Sobald Sie eine Verbindungsinstanz haben, können Sie eine SQL-Abfrage ausführen über [[yiidbCommand]].

SELECT-Abfrage

Die Abfrage gibt mehrere Zeilen zurück:

$command = $connection->createCommand('SELECT * FROM post');
$posts = $command->queryAll();
Nach dem Login kopieren

Gibt eine einzelne zurück Zeile:

$command = $connection->createCommand('SELECT * FROM post WHERE id=1');
$post = $command->queryOne();
Nach dem Login kopieren

Mehrzeiligen Einzelwert abfragen:

$command = $connection->createCommand('SELECT title FROM post');
$titles = $command->queryColumn();
Nach dem Login kopieren

Skalarwert/berechneter Wert abfragen:

$command = $connection->createCommand('SELECT COUNT(*) FROM post');
$postCount = $command->queryScalar();
Nach dem Login kopieren

UPDATE, INSERT, LÖSCHEN, Aktualisieren, Einfügen und Löschen usw.

Wenn Sie SQL ausführen, es werden keine Daten zurückgegeben. Sie können die Ausführungsmethode im Befehl verwenden:

$command = $connection->createCommand('UPDATE post SET status=1 WHERE id=1');
$command->execute();
Nach dem Login kopieren

Sie können die Methoden insert, update und delete verwenden , das basierend auf den Parametern entsprechendes SQL generiert und ausführt.

// 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();
Nach dem Login kopieren

Referenzierte Tabellen- und Spaltennamen

Meistens wird die folgende Syntax verwendet, um Tabellen- und Spaltennamen sicher in Anführungszeichen zu setzen:

$sql = "SELECT COUNT([[$column]]) FROM {{table}}";
$rowCount = $connection->createCommand($sql)->queryScalar();
Nach dem Login kopieren

Der obige Code [[$column]] wird konvertiert, um auf den entsprechenden Spaltennamen zu verweisen, und {{table}} Es wird in einen Verweis auf den entsprechenden Tabellennamen konvertiert. Der Tabellenname hat eine spezielle Variable {{%Y}}. Wenn ein Tabellenpräfix festgelegt ist, verwenden Sie diese Variante, um automatisch ein Präfix vor dem Tabellennamen hinzuzufügen:

$sql = "SELECT COUNT([[$column]]) FROM {{%$table}}";
$rowCount = $connection->createCommand($sql)->queryScalar();
Nach dem Login kopieren

Wenn das Tabellenpräfix in der Konfigurationsdatei wie folgt festgelegt ist, fragt der obige Code die Ergebnisse in der Tabelle tbl_table ab:

return [
  // ...
  'components' => [
    // ...
    'db' => [
      // ...
      'tablePrefix' => 'tbl_',
    ],
  ],
];
Nach dem Login kopieren

Tabellennamen und Spaltennamen manuell in Anführungszeichen setzen. Eine andere Möglichkeit ist die Verwendung von [[yiidbConnection::quoteTableName()]] und [[yiidbConnection::quoteColumnName()]]:

$column = $connection->quoteColumnName($column);
$table = $connection->quoteTableName($table);
$sql = "SELECT COUNT($column) FROM $table";
$rowCount = $connection->createCommand($sql)->queryScalar();
Nach dem Login kopieren

Vorverarbeitungsanweisungen

Vorverarbeitungsanweisungen können verwendet werden, um Abfrageparameter sicher zu übergeben und dann die Variable an zu binden der entsprechende Platzhalter:

$command = $connection->createCommand('SELECT * FROM post WHERE id=:id');
$command->bindValue(':id', $_GET['id']);
$post = $command->query();
Nach dem Login kopieren

Eine andere Verwendung besteht darin, eine vorbereitete Anweisung einmal vorzubereiten und mehrere Abfragen auszuführen:

$command = $connection->createCommand('DELETE FROM post WHERE id=:id');
$command->bindParam(':id', $id);

$id = 1;
$command->execute();

$id = 2;
$command->execute();
Nach dem Login kopieren

Tipp: Es ist effizienter, Variablen vor der Ausführung zu binden und dann den Wert der Variablen bei jeder Ausführung zu ändern (wird im Allgemeinen in Schleifen verwendet).

Transaktionen

Wenn Sie mehrere verwandte Abfragen nacheinander ausführen müssen, können Sie diese in eine Transaktion kapseln, um die Datenkonsistenz zu schützen. Yii bietet eine einfache Schnittstelle zum Ausführen der SQL-Transaktionsabfrageanweisung wie folgt:

$transaction = $connection->beginTransaction();
try {
  $connection->createCommand($sql1)->execute();
   $connection->createCommand($sql2)->execute();
  // ... 执行其他 SQL 语句 ...
  $transaction->commit();
} catch(Exception $e) {
  $transaction->rollBack();
}
Nach dem Login kopieren

Wir starten eine Transaktion über [[yiidbConnection::beginTransaction()|beginTransaction()]] und fangen die Ausnahme durch try Catch ab . Wenn die Ausführung erfolgreich ist, senden Sie die Transaktion und beenden Sie sie mit [[yiidbTransaction::commit()|commit()]]. Wenn eine Ausnahme auftritt und fehlschlägt, verwenden Sie [[yiidbTransaction::rollBack()|rollBack()]. ], um die Transaktion rückgängig zu machen.

Sie können bei Bedarf auch mehrere Transaktionen verschachteln: ​​

// 外部事务
$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();
}
Nach dem Login kopieren

Beachten Sie, dass die Datenbank Sie Die Verwendung muss Savepoints unterstützen, um korrekt ausgeführt zu werden. Der obige Code funktioniert in allen relationalen Daten. Er kann in beiden ausgeführt werden, die Sicherheit kann jedoch nur durch die Unterstützung von Savepoints gewährleistet werden.

Yii unterstützt auch das Festlegen von Isolationsstufen für Transaktionen. Bei der Ausführung einer Transaktion wird die Standardisolationsstufe der Datenbank verwendet. Sie können die Isolationsstufe für Dinge auch angeben häufig verwendete Isolationsstufen Level

[[yiidbTransaction::READ_UNCOMMITTED]] – Ermöglicht das Lesen geänderter, nicht festgeschriebener Daten, was zu Dirty Reads, nicht wiederholbaren Lesevorgängen und Phantom Reads führen kann

[ [ yiidbTransaction::READ_COMMITTED]] – Ermöglicht das Lesen, nachdem gleichzeitige Transaktionen festgeschrieben wurden, wodurch fehlerhafte Lesevorgänge vermieden werden können, die zu wiederholten Lesevorgängen und Phantom-Lesevorgängen führen können.

[[yiidbTransaction::REPEATABLE_READ]] – Mehrere Lesevorgänge desselben Felds führen zu konsistenten Ergebnissen, was zu Phantom-Lesevorgängen führen kann.

[[yiidbTransaction::SERIALIZABLE]] – Befolgt vollständig das ACID-Prinzip, um sicherzustellen, dass keine Dirty Reads, nicht wiederholbaren Reads und Phantom Reads auftreten.

Sie können die oben genannten Konstanten verwenden oder einen String-Befehl verwenden und den Befehl in der entsprechenden Datenbank ausführen, um die Isolationsstufe festzulegen. Der effektive Befehl für Postgres ist beispielsweise 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'],
  ],
]
Nach dem Login kopieren

以上的配置实现了一主多从的结构,从服务器用以执行读查询,主服务器执行写入查询,读写分离的功能由后台代码自动完成.调用者无须关心.例如:

// 使用以上配置创建数据库连接对象
$db = Yii::createObject($config);

// 通过从服务器执行查询操作
$rows = $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();

// 通过主服务器执行更新操作
$db->createCommand("UPDATE user SET username='demo' WHERE id=1")->execute();
Nach dem Login kopieren

注意:通过[[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'],
  ],
]
Nach dem Login kopieren

上述配置制定了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;
}
Nach dem Login kopieren

如果你想在从服务器上执行事务操作则必须要明确地指定,比如:

$transaction = $db->slave->beginTransaction();
Nach dem Login kopieren

有时你想强制使用主服务器来执行读查询,你可以调用seMaster()方法.

$rows = $db->useMaster(function ($db) {
  return $db->createCommand('SELECT * FROM user LIMIT 10')->queryAll();
});
Nach dem Login kopieren

你也可以设置$db->enableSlaves 为false来使所有查询都在主服务器上执行.

操作数据库模式

获得模式信息

你可以通过 [[yii\db\Schema]]实例来获取Schema信息:

$schema = $connection->getSchema();
Nach dem Login kopieren

该实例包括一系列方法来检索数据库多方面的信息:

$tables = $schema->getTableNames();
Nach dem Login kopieren

更多信息请参考[[yii\db\Schema]]

修改模式

除了基础的 SQL 查询,[[yii\db\Command]]还包括一系列方法来修改数据库模式:

  • 创建/重命名/删除/清空表

  • 增加/重命名/删除/修改字段

  • 增加/删除主键

  • 增加/删除外键

  • 创建/删除索引

使用示例:

// 创建表
$connection->createCommand()->createTable('post', [
  'id' => 'pk',
  'title' => 'string',
  'text' => 'text',
]);
Nach dem Login kopieren

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持PHP中文网。

更多yii2 数据库读写分离配置示例相关文章请关注PHP中文网!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage