Skip to content

Commit d74b5a5

Browse files
committed
navicat能通了
1 parent 158e11b commit d74b5a5

18 files changed

Lines changed: 1129 additions & 134 deletions

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
-**连接池**: 自动管理后端 MySQL 连接池,提高性能
1111
-**SQL 日志**: 完整的 SQL 执行日志记录
1212
-**协议兼容**: 支持基本的 MySQL 协议,包括查询、预处理语句等
13+
-**连接稳定性**: 自动连接恢复和超时处理,防止 "Lost connection" 错误
1314

1415
## 系统要求
1516

@@ -157,6 +158,34 @@ MySQL 代理 (端口 3317)
157158
- **认证失败**: 确认代理账号配置正确
158159
- **后端连接失败**: 检查后端 MySQL 服务器可访问性
159160
- **连接池耗尽**: 调整 `pool.size` 配置
161+
- **"2013 - Lost connection to MySQL server during query" 错误**:
162+
163+
**可能原因**
164+
- 连接超时时间过短
165+
- 查询执行时间过长
166+
- 网络连接不稳定
167+
- 连接池连接被意外关闭
168+
- USE命令响应包格式不正确(缺少状态标志)
169+
170+
**解决方案**
171+
1. 检查并调整超时配置(已在最新版本中优化)
172+
2. 修复USE命令响应包格式,添加SERVER_STATUS_AUTOCOMMIT标志
173+
4. 监控连接池状态和系统资源
174+
5. 调整MySQL服务器的超时参数
175+
6. 重启代理服务以应用修复
176+
177+
## 服务重启
178+
179+
修改配置或代码后,需要重启代理服务:
180+
181+
```bash
182+
# 如果使用Docker容器方式启动
183+
docker restart temp-hyperf-sqlLogProxy
184+
185+
# 或者重新启动Hyperf服务
186+
php bin/hyperf.php stop
187+
php bin/hyperf.php start
188+
```
160189

161190
## 开发说明
162191

app/Command/TestDbCommand.php

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Command;
6+
7+
use Hyperf\Command\Command as HyperfCommand;
8+
use Hyperf\Command\Annotation\Command;
9+
use Hyperf\DbConnection\Db;
10+
use Psr\Container\ContainerInterface;
11+
12+
/**
13+
* 测试数据库连接命令
14+
*/
15+
#[Command]
16+
class TestDbCommand extends HyperfCommand
17+
{
18+
public function __construct(protected ContainerInterface $container)
19+
{
20+
parent::__construct('db:test');
21+
}
22+
23+
public function configure()
24+
{
25+
parent::configure();
26+
$this->setDescription('测试数据库连接');
27+
}
28+
29+
public function handle()
30+
{
31+
$this->info('开始测试数据库连接...');
32+
33+
try {
34+
// 测试 backend_mysql 连接
35+
$this->info('测试 backend_mysql 连接...');
36+
$connection = Db::connection('backend_mysql');
37+
$this->info('获取连接对象成功');
38+
39+
// 检查连接对象的类型和可用方法
40+
$this->info('连接对象类型: ' . get_class($connection));
41+
$this->info('连接对象方法: ' . implode(', ', get_class_methods($connection)));
42+
43+
// 尝试不同的方法获取 PDO
44+
$pdo = null;
45+
if (method_exists($connection, 'getConnection')) {
46+
$pdo = $connection->getConnection();
47+
$this->info('通过 getConnection 获取 PDO');
48+
} elseif (method_exists($connection, 'getPdo')) {
49+
$pdo = $connection->getPdo();
50+
$this->info('通过 getPdo 获取 PDO');
51+
} elseif (method_exists($connection, 'getReadPdo')) {
52+
$pdo = $connection->getReadPdo();
53+
$this->info('通过 getReadPdo 获取 PDO');
54+
} elseif (method_exists($connection, 'getWritePdo')) {
55+
$pdo = $connection->getWritePdo();
56+
$this->info('通过 getWritePdo 获取 PDO');
57+
} else {
58+
$this->error('无法获取 PDO 对象');
59+
return;
60+
}
61+
62+
if ($pdo instanceof \PDO) {
63+
$this->info('PDO 对象有效,类型: ' . get_class($pdo));
64+
} else {
65+
$this->error('PDO 对象无效: ' . gettype($pdo) . ' 类: ' . (is_object($pdo) ? get_class($pdo) : 'N/A'));
66+
return;
67+
}
68+
69+
// 执行测试查询
70+
$result = $connection->select('SELECT 12 as test_value, NOW() as current_time');
71+
$this->info('查询执行成功: ' . json_encode($result));
72+
73+
} catch (\Throwable $e) {
74+
$this->error('数据库连接测试失败: ' . $e->getMessage());
75+
$this->error('文件: ' . $e->getFile() . ':' . $e->getLine());
76+
$this->error('Trace: ' . $e->getTraceAsString());
77+
}
78+
}
79+
}

app/Helpers/PHPSQLParserHelper.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace App\Helpers;
4+
5+
class PHPSQLParserHelper extends \PHPSQLParser\PHPSQLParser
6+
{
7+
public mixed $sql = '';
8+
public function __construct($sql = false, $calcPositions = false, array $options = array())
9+
{
10+
parent::__construct($sql, $calcPositions, $options);
11+
$this->sql = $sql;
12+
}
13+
14+
public function isSelect(): bool
15+
{
16+
return isset($this->parsed['SELECT']) || isset($this->parsed['SHOW']);
17+
}
18+
19+
}

app/Helpers/helpers.php

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/**
4+
* 获取 string.
5+
*
6+
* @param array $bytes
7+
*
8+
* @return string
9+
*/
10+
function bytes_to_string(array $bytes)
11+
{
12+
return implode(array_map('chr', $bytes));
13+
}
14+
15+
if (!function_exists('get_exception_hyperf_array')) {
16+
17+
/**
18+
* 转为可存储的数组
19+
*
20+
* @param \Throwable $exception
21+
* @return array
22+
*/
23+
function get_exception_hyperf_array($exception)
24+
{
25+
$exception_json = [
26+
'exception_class_name' => get_class($exception),
27+
'getMessage' => $exception->getMessage(),
28+
'getFile' => $exception->getFile(),
29+
'getCode' => $exception->getCode(),
30+
'getTraceAsStringArr' => explode("\n", $exception->getTraceAsString()),
31+
];
32+
33+
34+
if ($exception instanceof \Hyperf\Database\Exception\QueryException) {
35+
$exception_json['getSql'] = $exception->getSql();
36+
}
37+
38+
return $exception_json;
39+
}
40+
}

app/Protocol/MySql/Auth.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ class Auth
1212
public const CAPABILITIES = 0x00aff7df;
1313
private const MAX_PACKET_SIZE = 0xffffff;
1414

15+
public static $OK = [7, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0];
16+
1517
public static function generateAuthData(int $length = 20): string
1618
{
1719
$data = '';

app/Protocol/MySql/Packet.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ class Packet
1010
private int $sequenceId;
1111
private string $payload;
1212

13+
public $toBytes;
14+
1315
public function __construct(int $length, int $sequenceId, string $payload)
1416
{
1517
$this->length = $length;
@@ -47,6 +49,10 @@ public static function fromString(string $data): self
4749

4850
public function toBytes(): string
4951
{
52+
if ($this->toBytes) {
53+
return $this->toBytes;
54+
}
55+
5056
$len = pack('V', $this->length);
5157
return substr($len, 0, 3) . chr($this->sequenceId) . $this->payload;
5258
}

0 commit comments

Comments
 (0)