> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# 数据库配置

> 介绍 Laravel 的数据库连接配置、读写分离、多连接、SQL 执行、查询监听以及事务的基础知识。

## 简介

Laravel 官方支持以下数据库：

* MySQL / MariaDB
* PostgreSQL
* SQLite
* SQL Server

你可以使用相同的连接配置来执行原生 SQL、Query Builder 或 Eloquent ORM。

<Info>
  本页主要讲述数据库连接的前置知识。实际查询请参阅 [Query Builder](/zh/query-builder)，数据表结构管理请参阅 [Migrations](/zh/migrations)，初始数据填充请参阅 [Seeding](/zh/seeding)。
</Info>

## 配置

数据库配置集中存放在 `config/database.php`。
你可以通过 `default` 选择默认连接名，通过 `connections` 定义每个连接的详情。

```mermaid theme={null}
flowchart TD
    A[".env"] --> B["config/database.php"]
    B --> C["default connection"]
    B --> D["connections.mysql"]
    B --> E["connections.pgsql"]
    B --> F["connections.sqlite"]
    C --> G["DB facade / Query Builder / Eloquent"]
```

```php theme={null}
// config/database.php
'default' => env('DB_CONNECTION', 'sqlite'),

'connections' => [
    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'laravel'),
        'username' => env('DB_USERNAME', 'root'),
        'password' => env('DB_PASSWORD', ''),
    ],
],
```

在 `.env` 中至少要设置如下内容：

```ini theme={null}
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=app
DB_USERNAME=app_user
DB_PASSWORD=secret
```

如果使用 SQLite，请设置 `DB_CONNECTION=sqlite` 与 `DB_DATABASE` 的路径。

## 读写分离

如果希望将读操作（`SELECT`）与写操作（`INSERT` / `UPDATE` / `DELETE`）分派到不同主机，请在同一连接内配置 `read` 与 `write`。

```php theme={null}
'mysql' => [
    'driver' => 'mysql',
    'read' => [
        'host' => ['10.0.0.10', '10.0.0.11'],
    ],
    'write' => [
        'host' => ['10.0.0.20'],
    ],
    'sticky' => true,

    'port' => env('DB_PORT', '3306'),
    'database' => env('DB_DATABASE', 'laravel'),
    'username' => env('DB_USERNAME', 'root'),
    'password' => env('DB_PASSWORD', ''),
],
```

将 `sticky` 设置为 `true` 后，在同一请求内写入后的读取会固定使用写连接。

<Tip>
  在存在副本延迟的架构中，启用 `sticky` 可以降低刚写入后读到旧数据的风险。
</Tip>

## Pooled PostgreSQL 连接

当你使用 PgBouncer 之类以事务模式提供连接池的托管 PostgreSQL 服务时，请配置 `pooled` 与 `direct` 选项。

```php theme={null}
'pgsql' => [
    'driver' => 'pgsql',
    // ...
    'pooled' => env('DB_POOLED', false),
    'direct' => array_filter([
        'host' => env('DB_DIRECT_HOST'),
        'port' => env('DB_DIRECT_PORT'),
        'username' => env('DB_DIRECT_USERNAME'),
        'password' => env('DB_DIRECT_PASSWORD'),
        'sslmode' => env('DB_DIRECT_SSLMODE'),
    ]),
],
```

启用 `pooled` 后，Laravel 会自动进行路由分派。

| 操作                                      | 使用的连接                                |
| --------------------------------------- | ------------------------------------ |
| 应用查询                                    | pooled（自动启用模拟 prepare）               |
| 迁移 / `db:wipe` / `db:show` / `db:table` | direct（自动）                           |
| `php artisan db`                        | direct（默认），可通过 `--pooled` 切换至 pooled |

如果在应用代码中希望显式使用 direct 连接，请在连接名上追加 `::direct` 后缀。

```php theme={null}
DB::connection('pgsql::direct')->statement('create extension if not exists "uuid-ossp"');
```

## 多数据库连接

你可以在 `config/database.php` 中定义多个连接，并通过 `DB::connection()` 进行切换。

```php theme={null}
use Illuminate\Support\Facades\DB;

$users = DB::connection('sqlite')->select('select * from users');
$pdo = DB::connection('pgsql')->getPdo();
```

```mermaid theme={null}
flowchart LR
    A["DB::connection('mysql')"] --> B["Primary DB"]
    C["DB::connection('pgsql')"] --> D["Analytics DB"]
    E["DB::connection('sqlite')"] --> F["Local file DB"]
```

## 执行 SQL 查询

`DB` 门面按不同的查询类型提供了专用方法。

```php theme={null}
use Illuminate\Support\Facades\DB;

$users = DB::select('select * from users where active = ?', [1]);

DB::insert('insert into users (name, email) values (?, ?)', ['Taylor', 'taylor@example.com']);

$affected = DB::update('update users set votes = 100 where name = ?', ['Taylor']);

$deleted = DB::delete('delete from sessions where user_id = ?', [1]);

DB::statement('drop table temporary_imports');
```

<Warning>
  不要将用户输入直接拼接到 SQL 字符串中。请务必使用绑定参数，避免 SQL 注入。
</Warning>

## 查询监听

如果要跟踪已执行的 SQL，请在服务提供者的 `boot()` 中注册 `DB::listen()`。

```php theme={null}
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\DB;

public function boot(): void
{
    DB::listen(function (QueryExecuted $query) {
        logger()->debug('SQL executed', [
            'sql' => $query->toRawSql(),
            'time_ms' => $query->time,
        ]);
    });
}
```

## 事务

如果需要将多个更新作为一个单元处理，请使用 `DB::transaction()`。
一旦发生异常，Laravel 会自动回滚。

```php theme={null}
use Illuminate\Support\Facades\DB;

DB::transaction(function () {
    DB::update('update users set votes = 1');
    DB::delete('delete from posts where archived = 1');
});
```

如果需要死锁重试，可以指定 `attempts`。

```php theme={null}
DB::transaction(function () {
    // ...
}, attempts: 5);
```

如果需要手动控制，可以使用 `beginTransaction` / `rollBack` / `commit`。

```php theme={null}
DB::beginTransaction();

try {
    DB::update('update accounts set balance = balance - 100 where id = ?', [1]);
    DB::update('update accounts set balance = balance + 100 where id = ?', [2]);

    DB::commit();
} catch (\Throwable $e) {
    DB::rollBack();
    throw $e;
}
```

## 下一步

<Card title="Query Builder" icon="table" href="/zh/query-builder">
  学习如何借助连接配置安全地构建查询。
</Card>

<Card title="Migrations" icon="hammer" href="/zh/migrations">
  学习如何对已连接数据库的表结构进行版本管理。
</Card>

<Card title="Seeding" icon="seedling" href="/zh/seeding">
  学习如何以可复现的方式填充开发与测试数据。
</Card>


## Related topics

- [安装](/zh/installation.md)
- [Socialite - Laravel Bluesky](/zh/packages/laravel-bluesky/socialite.md)
- [MongoDB](/zh/mongodb.md)
- [配置](/zh/configuration.md)
- [数据库填充（Seeding）](/zh/seeding.md)
