Skip to content

Commit e5acf85

Browse files
Merge pull request #19786 from MauricioFauth/Innodb_getPageBufferpool-refactor
Refactor the Engines\Innodb::getPageBufferpool() method
2 parents ef4acb4 + 710ae6a commit e5acf85

File tree

8 files changed

+448
-290
lines changed

8 files changed

+448
-290
lines changed

phpstan-baseline.neon

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6030,24 +6030,6 @@ parameters:
60306030
count: 1
60316031
path: src/Encoding.php
60326032

6033-
-
6034-
message: '#^Binary operation "\*" between mixed and 100 results in an error\.$#'
6035-
identifier: binaryOp.invalid
6036-
count: 2
6037-
path: src/Engines/Innodb.php
6038-
6039-
-
6040-
message: '#^Binary operation "\*" between mixed and mixed results in an error\.$#'
6041-
identifier: binaryOp.invalid
6042-
count: 1
6043-
path: src/Engines/Innodb.php
6044-
6045-
-
6046-
message: '#^Binary operation "/" between \(float\|int\) and mixed results in an error\.$#'
6047-
identifier: binaryOp.invalid
6048-
count: 2
6049-
path: src/Engines/Innodb.php
6050-
60516033
-
60526034
message: '''
60536035
#^Call to deprecated method getInstance\(\) of class PhpMyAdmin\\Dbal\\DatabaseInterface\:
@@ -6057,18 +6039,6 @@ parameters:
60576039
count: 5
60586040
path: src/Engines/Innodb.php
60596041

6060-
-
6061-
message: '#^Loose comparison via "\=\=" is not allowed\.$#'
6062-
identifier: equal.notAllowed
6063-
count: 2
6064-
path: src/Engines/Innodb.php
6065-
6066-
-
6067-
message: '#^Parameter \#1 \$value of static method PhpMyAdmin\\Util\:\:formatNumber\(\) expects float\|int\|numeric\-string, mixed given\.$#'
6068-
identifier: argument.type
6069-
count: 11
6070-
path: src/Engines/Innodb.php
6071-
60726042
-
60736043
message: '#^Argument of an invalid type mixed supplied for foreach, only iterables are supported\.$#'
60746044
identifier: foreach.nonIterable

psalm-baseline.xml

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4096,29 +4096,6 @@
40964096
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
40974097
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
40984098
</DeprecatedMethod>
4099-
<MixedArgument>
4100-
<code><![CDATA[$status['Innodb_buffer_pool_pages_data']]]></code>
4101-
<code><![CDATA[$status['Innodb_buffer_pool_pages_dirty']]]></code>
4102-
<code><![CDATA[$status['Innodb_buffer_pool_pages_flushed']]]></code>
4103-
<code><![CDATA[$status['Innodb_buffer_pool_pages_free']]]></code>
4104-
<code><![CDATA[$status['Innodb_buffer_pool_pages_latched']]]></code>
4105-
<code><![CDATA[$status['Innodb_buffer_pool_pages_misc']]]></code>
4106-
<code><![CDATA[$status['Innodb_buffer_pool_pages_total']]]></code>
4107-
<code><![CDATA[$status['Innodb_buffer_pool_pages_total'] * $status['Innodb_page_size']]]></code>
4108-
<code><![CDATA[$status['Innodb_buffer_pool_read_requests']]]></code>
4109-
<code><![CDATA[$status['Innodb_buffer_pool_reads']]]></code>
4110-
<code><![CDATA[$status['Innodb_buffer_pool_reads'] * 100
4111-
/ $status['Innodb_buffer_pool_read_requests']]]></code>
4112-
<code><![CDATA[$status['Innodb_buffer_pool_wait_free']]]></code>
4113-
<code><![CDATA[$status['Innodb_buffer_pool_wait_free'] * 100
4114-
/ $status['Innodb_buffer_pool_write_requests']]]></code>
4115-
<code><![CDATA[$status['Innodb_buffer_pool_write_requests']]]></code>
4116-
</MixedArgument>
4117-
<MixedOperand>
4118-
<code><![CDATA[$status['Innodb_buffer_pool_pages_total']]]></code>
4119-
<code><![CDATA[$status['Innodb_buffer_pool_reads']]]></code>
4120-
<code><![CDATA[$status['Innodb_buffer_pool_wait_free']]]></code>
4121-
</MixedOperand>
41224099
</file>
41234100
<file src="src/Engines/Pbxt.php">
41244101
<PossiblyUnusedMethod>
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<table class="table table-striped table-hover w-auto float-start caption-top">
2+
<caption>{{ t('Buffer pool usage') }}</caption>
3+
<tbody>
4+
<tr>
5+
<th scope="row">{{ t('Free pages') }}</th>
6+
<td class="font-monospace text-end">{{ format_number(buffer_pool.pagesFree, 0) }}</td>
7+
</tr>
8+
<tr>
9+
<th scope="row">{{ t('Dirty pages') }}</th>
10+
<td class="font-monospace text-end">{{ format_number(buffer_pool.pagesDirty, 0) }}</td>
11+
</tr>
12+
<tr>
13+
<th scope="row">{{ t('Pages containing data') }}</th>
14+
<td class="font-monospace text-end">{{ format_number(buffer_pool.pagesData, 0) }}</td>
15+
</tr>
16+
<tr>
17+
<th scope="row">{{ t('Pages to be flushed') }}</th>
18+
<td class="font-monospace text-end">{{ format_number(buffer_pool.pagesFlushed, 0) }}</td>
19+
</tr>
20+
<tr>
21+
<th scope="row">{{ t('Busy pages') }}</th>
22+
<td class="font-monospace text-end">{{ format_number(buffer_pool.pagesMisc, 0) }}</td>
23+
</tr>
24+
{% if buffer_pool.pagesLatched != null %}
25+
<tr>
26+
<th scope="row">{{ t('Latched pages') }}</th>
27+
<td class="font-monospace text-end">{{ format_number(buffer_pool.pagesLatched, 0) }}</td>
28+
</tr>
29+
{% endif %}
30+
</tbody>
31+
<tfoot>
32+
<tr>
33+
<th colspan="2">
34+
{{ t('Total:') }} {{ t('%s pages')|format(format_number(buffer_pool.pagesTotal, 0)) }} / {{ format_byte_down(buffer_pool.pagesTotal * buffer_pool.innodbPageSize)|join(' ') }}
35+
</th>
36+
</tr>
37+
</tfoot>
38+
</table>
39+
40+
<table class="table table-striped table-hover w-auto ms-4 float-start caption-top">
41+
<caption>{{ t('Buffer pool activity') }}</caption>
42+
<tbody>
43+
<tr>
44+
<th scope="row">{{ t('Read requests') }}</th>
45+
<td class="font-monospace text-end">{{ format_number(buffer_pool.readRequests, 0) }}</td>
46+
</tr>
47+
<tr>
48+
<th scope="row">{{ t('Write requests') }}</th>
49+
<td class="font-monospace text-end">{{ format_number(buffer_pool.writeRequests, 0) }}</td>
50+
</tr>
51+
<tr>
52+
<th scope="row">{{ t('Read misses') }}</th>
53+
<td class="font-monospace text-end">{{ format_number(buffer_pool.reads, 0) }}</td>
54+
</tr>
55+
<tr>
56+
<th scope="row">{{ t('Write waits') }}</th>
57+
<td class="font-monospace text-end">{{ format_number(buffer_pool.waitFree, 0) }}</td>
58+
</tr>
59+
<tr>
60+
<th scope="row">{{ t('Read misses in %') }}</th>
61+
<td class="font-monospace text-end">
62+
{{- buffer_pool.readRequests != 0 ? format_number(buffer_pool.reads * 100 / buffer_pool.readRequests, 3, 2) ~ '%' : '---' -}}
63+
</td>
64+
</tr>
65+
<tr>
66+
<th scope="row">{{ t('Write waits in %') }}</th>
67+
<td class="font-monospace text-end">
68+
{{- buffer_pool.writeRequests != 0 ? format_number(buffer_pool.waitFree * 100 / buffer_pool.writeRequests, 3, 2) ~ '%' : '---' -}}
69+
</td>
70+
</tr>
71+
</tbody>
72+
</table>

src/Engines/Innodb.php

Lines changed: 16 additions & 139 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,16 @@
11
<?php
2-
/**
3-
* The InnoDB storage engine
4-
*/
52

63
declare(strict_types=1);
74

85
namespace PhpMyAdmin\Engines;
96

107
use PhpMyAdmin\Dbal\DatabaseInterface;
8+
use PhpMyAdmin\Engines\Innodb\BufferPool;
119
use PhpMyAdmin\StorageEngine;
12-
use PhpMyAdmin\Util;
10+
use PhpMyAdmin\Template;
1311

1412
use function __;
1513
use function htmlspecialchars;
16-
use function implode;
1714

1815
/**
1916
* The InnoDB storage engine
@@ -110,141 +107,11 @@ public function getInfoPages(): array
110107
*
111108
* @return string html table with stats
112109
*/
113-
public function getPageBufferpool(): string
110+
public function getPageBufferPool(): string
114111
{
115-
// The following query is only possible because we know
116-
// that we are on MySQL 5 here (checked above)!
117-
// side note: I love MySQL 5 for this. :-)
118-
$sql = 'SHOW STATUS'
119-
. ' WHERE Variable_name LIKE \'Innodb\\_buffer\\_pool\\_%\''
120-
. ' OR Variable_name = \'Innodb_page_size\';';
121-
$status = DatabaseInterface::getInstance()->fetchResult($sql, 0, 1);
122-
123-
/** @var string[] $bytes */
124-
$bytes = Util::formatByteDown($status['Innodb_buffer_pool_pages_total'] * $status['Innodb_page_size']);
125-
126-
$output = '<table class="table table-striped table-hover w-auto float-start caption-top">' . "\n"
127-
. ' <caption>' . "\n"
128-
. ' ' . __('Buffer Pool Usage') . "\n"
129-
. ' </caption>' . "\n"
130-
. ' <tfoot>' . "\n"
131-
. ' <tr>' . "\n"
132-
. ' <th colspan="2">' . "\n"
133-
. ' ' . __('Total:') . ' '
134-
. Util::formatNumber($status['Innodb_buffer_pool_pages_total'], 0)
135-
. '&nbsp;' . __('pages')
136-
. ' / '
137-
. implode('&nbsp;', $bytes) . "\n"
138-
. ' </th>' . "\n"
139-
. ' </tr>' . "\n"
140-
. ' </tfoot>' . "\n"
141-
. ' <tbody>' . "\n"
142-
. ' <tr>' . "\n"
143-
. ' <th scope="row">' . __('Free pages') . '</th>' . "\n"
144-
. ' <td class="font-monospace text-end">'
145-
. Util::formatNumber($status['Innodb_buffer_pool_pages_free'], 0)
146-
. '</td>' . "\n"
147-
. ' </tr>' . "\n"
148-
. ' <tr>' . "\n"
149-
. ' <th scope="row">' . __('Dirty pages') . '</th>' . "\n"
150-
. ' <td class="font-monospace text-end">'
151-
. Util::formatNumber($status['Innodb_buffer_pool_pages_dirty'], 0)
152-
. '</td>' . "\n"
153-
. ' </tr>' . "\n"
154-
. ' <tr>' . "\n"
155-
. ' <th scope="row">' . __('Pages containing data') . '</th>' . "\n"
156-
. ' <td class="font-monospace text-end">'
157-
. Util::formatNumber($status['Innodb_buffer_pool_pages_data'], 0) . "\n"
158-
. '</td>' . "\n"
159-
. ' </tr>' . "\n"
160-
. ' <tr>' . "\n"
161-
. ' <th scope="row">' . __('Pages to be flushed') . '</th>' . "\n"
162-
. ' <td class="font-monospace text-end">'
163-
. Util::formatNumber($status['Innodb_buffer_pool_pages_flushed'], 0) . "\n"
164-
. '</td>' . "\n"
165-
. ' </tr>' . "\n"
166-
. ' <tr>' . "\n"
167-
. ' <th scope="row">' . __('Busy pages') . '</th>' . "\n"
168-
. ' <td class="font-monospace text-end">'
169-
. Util::formatNumber($status['Innodb_buffer_pool_pages_misc'], 0) . "\n"
170-
. '</td>' . "\n"
171-
. ' </tr>';
172-
173-
// not present at least since MySQL 5.1.40
174-
if (isset($status['Innodb_buffer_pool_pages_latched'])) {
175-
$output .= ' <tr>'
176-
. ' <th scope="row">' . __('Latched pages') . '</th>'
177-
. ' <td class="font-monospace text-end">'
178-
. Util::formatNumber($status['Innodb_buffer_pool_pages_latched'], 0)
179-
. '</td>'
180-
. ' </tr>';
181-
}
182-
183-
$output .= ' </tbody>' . "\n"
184-
. '</table>' . "\n\n"
185-
. '<table class="table table-striped table-hover w-auto ms-4 float-start caption-top">' . "\n"
186-
. ' <caption>' . "\n"
187-
. ' ' . __('Buffer Pool Activity') . "\n"
188-
. ' </caption>' . "\n"
189-
. ' <tbody>' . "\n"
190-
. ' <tr>' . "\n"
191-
. ' <th scope="row">' . __('Read requests') . '</th>' . "\n"
192-
. ' <td class="font-monospace text-end">'
193-
. Util::formatNumber($status['Innodb_buffer_pool_read_requests'], 0) . "\n"
194-
. '</td>' . "\n"
195-
. ' </tr>' . "\n"
196-
. ' <tr>' . "\n"
197-
. ' <th scope="row">' . __('Write requests') . '</th>' . "\n"
198-
. ' <td class="font-monospace text-end">'
199-
. Util::formatNumber($status['Innodb_buffer_pool_write_requests'], 0) . "\n"
200-
. '</td>' . "\n"
201-
. ' </tr>' . "\n"
202-
. ' <tr>' . "\n"
203-
. ' <th scope="row">' . __('Read misses') . '</th>' . "\n"
204-
. ' <td class="font-monospace text-end">'
205-
. Util::formatNumber($status['Innodb_buffer_pool_reads'], 0) . "\n"
206-
. '</td>' . "\n"
207-
. ' </tr>' . "\n"
208-
. ' <tr>' . "\n"
209-
. ' <th scope="row">' . __('Write waits') . '</th>' . "\n"
210-
. ' <td class="font-monospace text-end">'
211-
. Util::formatNumber($status['Innodb_buffer_pool_wait_free'], 0) . "\n"
212-
. '</td>' . "\n"
213-
. ' </tr>' . "\n"
214-
. ' <tr>' . "\n"
215-
. ' <th scope="row">' . __('Read misses in %') . '</th>' . "\n"
216-
. ' <td class="font-monospace text-end">'
217-
. ($status['Innodb_buffer_pool_read_requests'] == 0
218-
? '---'
219-
: htmlspecialchars(
220-
Util::formatNumber(
221-
$status['Innodb_buffer_pool_reads'] * 100
222-
/ $status['Innodb_buffer_pool_read_requests'],
223-
3,
224-
2,
225-
),
226-
) . ' %') . "\n"
227-
. '</td>' . "\n"
228-
. ' </tr>' . "\n"
229-
. ' <tr>' . "\n"
230-
. ' <th scope="row">' . __('Write waits in %') . '</th>' . "\n"
231-
. ' <td class="font-monospace text-end">'
232-
. ($status['Innodb_buffer_pool_write_requests'] == 0
233-
? '---'
234-
: htmlspecialchars(
235-
Util::formatNumber(
236-
$status['Innodb_buffer_pool_wait_free'] * 100
237-
/ $status['Innodb_buffer_pool_write_requests'],
238-
3,
239-
2,
240-
),
241-
) . ' %') . "\n"
242-
. '</td>' . "\n"
243-
. ' </tr>' . "\n"
244-
. ' </tbody>' . "\n"
245-
. '</table>' . "\n";
246-
247-
return $output;
112+
return (new Template())->render('server/engines/_innodb_buffer_pool', [
113+
'buffer_pool' => $this->getBufferPoolStatus(),
114+
]);
248115
}
249116

250117
/**
@@ -313,4 +180,14 @@ public function supportsFilePerTable(): bool
313180

314181
return $dbi->fetchValue("SHOW GLOBAL VARIABLES LIKE 'innodb_file_per_table';", 1) === 'ON';
315182
}
183+
184+
private function getBufferPoolStatus(): BufferPool
185+
{
186+
$result = DatabaseInterface::getInstance()->tryQuery(
187+
"SHOW STATUS WHERE Variable_name LIKE 'Innodb\\_buffer\\_pool\\_%' OR Variable_name = 'Innodb_page_size';",
188+
cacheAffectedRows: false,
189+
);
190+
191+
return BufferPool::fromResult($result !== false ? $result->fetchAllKeyPair() : []);
192+
}
316193
}

src/Engines/Innodb/BufferPool.php

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\Engines\Innodb;
6+
7+
use function is_numeric;
8+
9+
/**
10+
* @see https://dev.mysql.com/doc/refman/en/innodb-buffer-pool.html
11+
* @see https://mariadb.com/docs/server/server-usage/storage-engines/innodb/innodb-buffer-pool
12+
*/
13+
final readonly class BufferPool
14+
{
15+
/**
16+
* @param numeric-string $innodbPageSize Innodb_page_size
17+
* @param numeric-string $pagesData Innodb_buffer_pool_pages_data
18+
* @param numeric-string $pagesDirty Innodb_buffer_pool_pages_dirty
19+
* @param numeric-string $pagesFlushed Innodb_buffer_pool_pages_flushed
20+
* @param numeric-string $pagesFree Innodb_buffer_pool_pages_free
21+
* @param numeric-string $pagesMisc Innodb_buffer_pool_pages_misc
22+
* @param numeric-string $pagesTotal Innodb_buffer_pool_pages_total
23+
* @param numeric-string $readRequests Innodb_buffer_pool_read_requests
24+
* @param numeric-string $reads Innodb_buffer_pool_reads
25+
* @param numeric-string $waitFree Innodb_buffer_pool_wait_free
26+
* @param numeric-string $writeRequests Innodb_buffer_pool_write_requests
27+
* @param numeric-string|null $pagesLatched Innodb_buffer_pool_pages_latched
28+
*/
29+
public function __construct(
30+
public string $innodbPageSize,
31+
public string $pagesData,
32+
public string $pagesDirty,
33+
public string $pagesFlushed,
34+
public string $pagesFree,
35+
public string $pagesMisc,
36+
public string $pagesTotal,
37+
public string $readRequests,
38+
public string $reads,
39+
public string $waitFree,
40+
public string $writeRequests,
41+
public string|null $pagesLatched,
42+
) {
43+
}
44+
45+
/** @param array<string|null> $result */
46+
public static function fromResult(array $result): self
47+
{
48+
return new self(
49+
self::getNumeric($result['Innodb_page_size'] ?? null) ?? '0',
50+
self::getNumeric($result['Innodb_buffer_pool_pages_data'] ?? null) ?? '0',
51+
self::getNumeric($result['Innodb_buffer_pool_pages_dirty'] ?? null) ?? '0',
52+
self::getNumeric($result['Innodb_buffer_pool_pages_flushed'] ?? null) ?? '0',
53+
self::getNumeric($result['Innodb_buffer_pool_pages_free'] ?? null) ?? '0',
54+
self::getNumeric($result['Innodb_buffer_pool_pages_misc'] ?? null) ?? '0',
55+
self::getNumeric($result['Innodb_buffer_pool_pages_total'] ?? null) ?? '0',
56+
self::getNumeric($result['Innodb_buffer_pool_read_requests'] ?? null) ?? '0',
57+
self::getNumeric($result['Innodb_buffer_pool_reads'] ?? null) ?? '0',
58+
self::getNumeric($result['Innodb_buffer_pool_wait_free'] ?? null) ?? '0',
59+
self::getNumeric($result['Innodb_buffer_pool_write_requests'] ?? null) ?? '0',
60+
self::getNumeric($result['Innodb_buffer_pool_pages_latched'] ?? null),
61+
);
62+
}
63+
64+
/** @return numeric-string|null */
65+
private static function getNumeric(string|null $value): string|null
66+
{
67+
return is_numeric($value) ? $value : null;
68+
}
69+
}

0 commit comments

Comments
 (0)