Skip to content

Commit b5a8874

Browse files
authored
优化数据库操作判断断线错误码,自动关闭连接 (#244)
1 parent 0c2ee24 commit b5a8874

7 files changed

Lines changed: 261 additions & 56 deletions

File tree

src/Db/Contract/IPgsqlDb.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@
88

99
interface IPgsqlDb extends IDb
1010
{
11+
/**
12+
* 检查错误码是否为掉线
13+
*/
14+
public function checkCodeIsOffline(string $code): bool;
1115
}

src/Db/Drivers/PdoPgsql/Driver.php

Lines changed: 147 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
use Imi\Db\Exception\DbException;
1111
use Imi\Db\Statement\StatementManager;
1212
use Imi\Db\Transaction\Transaction;
13-
use Imi\Pgsql\Db\Contract\IPgsqlDb;
1413
use Imi\Pgsql\Db\Contract\IPgsqlStatement;
1514
use Imi\Pgsql\Db\PgsqlBase;
1615
use Imi\Pgsql\Db\Util\SqlUtil;
@@ -21,7 +20,7 @@
2120
*
2221
* @Bean("PdoPgsqlDriver")
2322
*/
24-
class Driver extends PgsqlBase implements IPgsqlDb
23+
class Driver extends PgsqlBase
2524
{
2625
/**
2726
* 连接对象
@@ -104,14 +103,30 @@ public function isConnected(): bool
104103
*/
105104
public function ping(): bool
106105
{
106+
$instance = $this->instance;
107+
if (!$instance)
108+
{
109+
return false;
110+
}
107111
try
108112
{
109-
$instance = $this->instance;
113+
if ($instance->query('select 1'))
114+
{
115+
return true;
116+
}
117+
if ($this->checkCodeIsOffline($instance->errorInfo()[0] ?? ''))
118+
{
119+
$this->close();
120+
}
110121

111-
return $instance && false !== $instance->query('select 1');
122+
return false;
112123
}
113-
catch (\Throwable $e)
124+
catch (\PDOException $e)
114125
{
126+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
127+
{
128+
$this->close();
129+
}
115130
}
116131

117132
return false;
@@ -140,12 +155,13 @@ public function close(): void
140155
$this->lastStmt = null;
141156
}
142157
$this->instance = null;
158+
$this->transaction->init();
143159
}
144160

145161
/**
146162
* {@inheritDoc}
147163
*/
148-
public function getInstance(): PDO
164+
public function getInstance(): ?PDO
149165
{
150166
return $this->instance;
151167
}
@@ -155,12 +171,28 @@ public function getInstance(): PDO
155171
*/
156172
public function beginTransaction(): bool
157173
{
158-
if (!$this->inTransaction() && !$this->instance->beginTransaction())
174+
try
159175
{
160-
return false;
176+
if (!$this->inTransaction() && !$this->instance->beginTransaction())
177+
{
178+
if ($this->checkCodeIsOffline($this->instance->errorInfo()[0] ?? ''))
179+
{
180+
$this->close();
181+
}
182+
183+
return false;
184+
}
185+
$this->exec('SAVEPOINT P' . $this->getTransactionLevels());
186+
$this->transaction->beginTransaction();
187+
}
188+
catch (\PDOException $e)
189+
{
190+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
191+
{
192+
$this->close();
193+
}
194+
throw $e;
161195
}
162-
$this->exec('SAVEPOINT P' . $this->getTransactionLevels());
163-
$this->transaction->beginTransaction();
164196

165197
return true;
166198
}
@@ -170,7 +202,28 @@ public function beginTransaction(): bool
170202
*/
171203
public function commit(): bool
172204
{
173-
return $this->instance->commit() && $this->transaction->commit();
205+
try
206+
{
207+
if (!$this->instance->commit())
208+
{
209+
if ($this->checkCodeIsOffline($this->instance->errorInfo()[0] ?? ''))
210+
{
211+
$this->close();
212+
}
213+
214+
return false;
215+
}
216+
}
217+
catch (\PDOException $e)
218+
{
219+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
220+
{
221+
$this->close();
222+
}
223+
throw $e;
224+
}
225+
226+
return $this->transaction->commit();
174227
}
175228

176229
/**
@@ -180,7 +233,18 @@ public function rollBack(?int $levels = null): bool
180233
{
181234
if (null === $levels)
182235
{
183-
$result = $this->instance->rollback();
236+
try
237+
{
238+
$result = $this->instance->rollback();
239+
}
240+
catch (\PDOException $e)
241+
{
242+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
243+
{
244+
$this->close();
245+
}
246+
throw $e;
247+
}
184248
}
185249
else
186250
{
@@ -191,6 +255,10 @@ public function rollBack(?int $levels = null): bool
191255
{
192256
$this->transaction->rollBack($levels);
193257
}
258+
elseif ($this->checkCodeIsOffline($this->instance->errorInfo()[0] ?? ''))
259+
{
260+
$this->close();
261+
}
194262

195263
return $result;
196264
}
@@ -261,11 +329,29 @@ public function lastSql(): string
261329
public function exec(string $sql): int
262330
{
263331
$this->lastSql = $sql;
332+
$this->lastStmt = null;
264333

265-
$result = $this->instance->exec($sql);
266-
if (false === $result)
334+
try
267335
{
268-
throw new DbException('SQL prepare error [' . $this->errorCode() . '] ' . $this->errorInfo() . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL);
336+
$result = $this->instance->exec($sql);
337+
if (false === $result)
338+
{
339+
$errorCode = $this->errorCode();
340+
$errorInfo = $this->errorInfo();
341+
if ($this->checkCodeIsOffline($this->instance->errorInfo()[0] ?? ''))
342+
{
343+
$this->close();
344+
}
345+
throw new DbException('SQL exec error [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL);
346+
}
347+
}
348+
catch (\PDOException $e)
349+
{
350+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
351+
{
352+
$this->close();
353+
}
354+
throw $e;
269355
}
270356

271357
return $result;
@@ -330,17 +416,34 @@ public function prepare(string $sql, array $driverOptions = []): IPgsqlStatement
330416
}
331417
else
332418
{
333-
$this->lastSql = $sql;
334-
$lastStmt = $this->lastStmt = $this->instance->prepare($sql, $driverOptions);
335-
// @phpstan-ignore-next-line
336-
if (false === $lastStmt)
419+
try
337420
{
338-
throw new DbException('SQL prepare error [' . $this->errorCode() . '] ' . $this->errorInfo() . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL);
421+
$this->lastSql = $sql;
422+
$lastStmt = $this->lastStmt = $this->instance->prepare($sql, $driverOptions);
423+
// @phpstan-ignore-next-line
424+
if (false === $lastStmt)
425+
{
426+
$errorCode = $this->errorCode();
427+
$errorInfo = $this->errorInfo();
428+
if ($this->checkCodeIsOffline($this->instance->errorInfo()[0] ?? ''))
429+
{
430+
$this->close();
431+
}
432+
throw new DbException('SQL prepare error [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL);
433+
}
434+
$stmt = App::getBean(Statement::class, $this, $lastStmt);
435+
if ($this->isCacheStatement && !isset($stmtCache))
436+
{
437+
StatementManager::setNX($stmt, true);
438+
}
339439
}
340-
$stmt = App::getBean(Statement::class, $this, $lastStmt);
341-
if ($this->isCacheStatement && !isset($stmtCache))
440+
catch (\PDOException $e)
342441
{
343-
StatementManager::setNX($stmt, true);
442+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
443+
{
444+
$this->close();
445+
}
446+
throw $e;
344447
}
345448
}
346449

@@ -352,11 +455,28 @@ public function prepare(string $sql, array $driverOptions = []): IPgsqlStatement
352455
*/
353456
public function query(string $sql): IPgsqlStatement
354457
{
355-
$this->lastSql = $sql;
356-
$this->lastStmt = $lastStmt = $this->instance->query($sql);
357-
if (false === $lastStmt)
458+
try
358459
{
359-
throw new DbException('SQL query error: [' . $this->errorCode() . '] ' . $this->errorInfo() . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL);
460+
$this->lastSql = $sql;
461+
$this->lastStmt = $lastStmt = $this->instance->query($sql);
462+
if (false === $lastStmt)
463+
{
464+
$errorCode = $this->errorCode();
465+
$errorInfo = $this->errorInfo();
466+
if ($this->checkCodeIsOffline($this->instance->errorInfo()[0] ?? ''))
467+
{
468+
$this->close();
469+
}
470+
throw new DbException('SQL query error [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $sql . \PHP_EOL);
471+
}
472+
}
473+
catch (\PDOException $e)
474+
{
475+
if ($this->checkCodeIsOffline($e->errorInfo[0]))
476+
{
477+
$this->close();
478+
}
479+
throw $e;
360480
}
361481

362482
return App::getBean(Statement::class, $this, $lastStmt);

src/Db/Drivers/PdoPgsql/Statement.php

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -128,28 +128,45 @@ public function getSql(): string
128128
*/
129129
public function execute(array $inputParameters = null): bool
130130
{
131-
$statement = $this->statement;
132-
$statement->closeCursor();
133-
if ($inputParameters)
131+
try
134132
{
135-
foreach ($inputParameters as $k => $v)
133+
$statement = $this->statement;
134+
$statement->closeCursor();
135+
if ($inputParameters)
136136
{
137-
if (is_numeric($k))
137+
foreach ($inputParameters as $k => $v)
138138
{
139-
$statement->bindValue($k + 1, $v, $this->getDataTypeByValue($v));
139+
if (is_numeric($k))
140+
{
141+
$statement->bindValue($k + 1, $v, $this->getDataTypeByValue($v));
142+
}
143+
else
144+
{
145+
$statement->bindValue($k, $v, $this->getDataTypeByValue($v));
146+
}
140147
}
141-
else
148+
}
149+
$result = $statement->execute();
150+
if (!$result)
151+
{
152+
$errorCode = $this->errorCode();
153+
$errorInfo = $this->errorInfo();
154+
if ($this->db->checkCodeIsOffline($this->db->errorInfo()[0] ?? ''))
142155
{
143-
$statement->bindValue($k, $v, $this->getDataTypeByValue($v));
156+
$this->db->close();
144157
}
158+
throw new DbException('SQL query error [' . $errorCode . '] ' . $errorInfo . \PHP_EOL . 'sql: ' . $this->getSql() . \PHP_EOL);
145159
}
160+
$this->updateLastInsertId();
146161
}
147-
$result = $statement->execute();
148-
if (!$result)
162+
catch (\PDOException $e)
149163
{
150-
throw new DbException('SQL query error: [' . $this->errorCode() . '] ' . $this->errorInfo() . ' sql: ' . $this->getSql());
164+
if ($this->db->checkCodeIsOffline($e->errorInfo[0]))
165+
{
166+
$this->db->close();
167+
}
168+
throw $e;
151169
}
152-
$this->updateLastInsertId();
153170

154171
return $result;
155172
}

0 commit comments

Comments
 (0)