# OPcache izskaidrots: PHP baitkoda kešatmiņa

> OPcache izskaidrots: kā darbojas PHP baitkoda kešatmiņa, kuri iestatījumi ir svarīgi, kāpēc pēc atjauninājumiem tā jātīra un kā to nodrošināt pret riskiem.

Avots: https://phpsos.de/lv/php/opcache/  
Aktuāls uz: 25.10.2026  
Pakalpojuma sniedzējs: PHP SOS, PHP ārkārtas palīdzība un serveru drošība. Tūlītēja palīdzība pa WhatsApp: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20nepiecie%C5%A1ama%20pal%C4%ABdz%C4%ABba%20ar%20m%C5%ABsu%20PHP%20serveri.%20Uz%C5%86%C4%93mums%3A%20%E2%80%A6%20Vietne%3A%20%E2%80%A6

**Īsi:** OPcache ir PHP iebūvētā baitkoda kešatmiņa. Saskaņā ar rokasgrāmatu tā glabā iepriekš kompilētu baitkodu koplietojamā atmiņā, tāpēc PHP skriptus nav jāielādē un jāpārveido katrā pieprasījumā. Tas ir komplektā kopš PHP 5.5.0. OPcache padara PHP ātrāku, bet neaizstāj atjauninājumu: pēc PHP ielāpa jāpārstartē visi PHP procesi, nepietiek tikai ar kešatmiņas iztīrīšanu.

## Ko OPcache dara precīzi?

Katrā pieprasījumā PHP skripts jānolasa, jāsadala un jāpārveido opcodes, tas ir, komandās [Zend Engine](https://phpsos.de/lv/php/zend-engine/) virtuālajai mašīnai. CMS ar simtiem failu tas ir liels darbs, kas pastāvīgi atkārtojas.

OPcache šīs pārveides rezultātu glabā koplietojamā atmiņā (Shared Memory). Tai piekļūst visi PHP-FPM pakalpojuma darbprocesi vai visi Apache procesi ar mod_php. Ja fails nemainās, tā baitkods tiek izmantots atkārtoti tieši.

OPcache ielādē kā Zend paplašinājumu, nevis kā parastu paplašinājumu:

```ini
; Linux (ceļš atkarībā no pakotnes)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
```

Saskaņā ar rokasgrāmatu OPcache jāielādē pirms Xdebug, ja abi ir aktīvi.

Svarīgi, kam pieder koplietojamā atmiņa. PHP-FPM gadījumā to izveido galvenais process (master), un to izmanto visi šī pakalpojuma visu pūlu darbprocesi. mod_php gadījumā tā pieder Apache galvenajam procesam. Pakalpojuma pārstartēšana tāpēc kešatmiņu iztīra pilnībā, bet atsevišķs jauns darbprocess ne. Komandrindai nav koplietojamas atmiņas starp izsaukumiem, jo katrs izsaukums ir atsevišķs process; tur OPcache pēc noklusējuma ir izslēgts.

Lēmumu pieņēmējiem pietiek ar vienu praktisku likumu: OPcache ražošanas serveros gandrīz vienmēr ir lietderīgs, bet prasa skaidru kārtību izvietošanai un atjauninājumiem.

## Kuri OPcache iestatījumi ir svarīgi?

Turpmākās vērtības ņemtas no PHP rokasgrāmatas konfigurācijas lapas. Sleja „Mainīgums“ rāda, kur iestatījumu drīkst iestatīt: `INI_SYSTEM` tikai php.ini vai servera konfigurācijā, `INI_ALL` jebkur.

| Direktīva | Noklusējums | Mainīgums | Nozīme |
|---|---|---|---|
| `opcache.enable` | 1 | INI_ALL | kešatmiņa ieslēgta vai izslēgta, izpildes laikā var tikai izslēgt |
| `opcache.enable_cli` | 0 | INI_SYSTEM | kešatmiņa komandrindai |
| `opcache.memory_consumption` | 128 | INI_SYSTEM | koplietojamās atmiņas lielums MB |
| `opcache.interned_strings_buffer` | 8 | INI_SYSTEM | atmiņa kopīgajām virknēm MB |
| `opcache.max_accelerated_files` | 10000 | INI_SYSTEM | kešoto skriptu maksimālais skaits |
| `opcache.validate_timestamps` | 1 | INI_ALL | pārbauda, vai faili ir mainīti |
| `opcache.revalidate_freq` | 2 | INI_ALL | pārbaudes intervāls sekundēs, 0 = katrā pieprasījumā |
| `opcache.restrict_api` | tukšs | INI_SYSTEM | atļauj API funkcijas tikai no norādīta ceļa |
| `opcache.validate_permission` | 0 | INI_SYSTEM | pārbauda failu tiesības pret pašreizējo lietotāju |
| `opcache.validate_root` | 0 | INI_SYSTEM | novērš nosaukumu sadursmes chroot vidē |
| `opcache.file_cache` | tukšs | INI_SYSTEM | otrais kešatmiņas līmenis diskā |

Tipiska ražošanas konfigurācija varētu izskatīties šādi. Vērtības iepriekš pārbaudiet ar savu lietojumprogrammu:

```ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=20000
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.restrict_api=/var/www/admin-tools
```

Kas iestata `opcache.validate_timestamps=0`, iegūst nedaudz veiktspējas. Taču tad OPcache mainītus failus vairs neatpazīst vispār, un katrai izvietošanai vajadzīga kešatmiņas atiestatīšana vai pārstartēšana.

## Kešatmiņas novērošana un mērķtiecīga tīrīšana

OPcache nāk ar savām funkcijām, to vidū `opcache_get_status()`, `opcache_get_configuration()`, `opcache_invalidate()` un `opcache_reset()`. Īss, tikai lasošs skats uz aizpildījumu:

```php
<?php
$status = opcache_get_status(false);
if ($status === false) {
    exit("OPcache ist nicht aktiv.\n");
}
printf("Gecachte Skripte: %d\n", $status['opcache_statistics']['num_cached_scripts']);
printf("Freier Speicher: %.1f MB\n", $status['memory_usage']['free_memory'] / 1048576);
```

Serveros ar vairākām vietnēm ne katrai lietojumprogrammai vajadzētu būt iespējai iztīrīt vai nolasīt visu pārējo kešatmiņu. Tam paredzēts `opcache.restrict_api`: API funkcijas drīkst izsaukt tikai skripti zem norādītā ceļa.

## JIT: mašīnkoda kompilators OPcache

Kopš PHP 8.0 OPcache ir JIT kompilators, kas opcodes pārveido mašīnkodā. Saskaņā ar JIT RFC tas ir gandrīz patstāvīga OPcache daļa un izveidoto kodu glabā savā koplietojamās atmiņas apgabalā. Vada to ar `opcache.jit` un `opcache.jit_buffer_size`. Kopš PHP 8.4.0 `opcache.jit` pēc noklusējuma ir `disable`. Kad JIT ir vērts izmantot, izskaidro raksts [JIT un veiktspēja PHP 8](https://phpsos.de/lv/php/jit-und-performance/).

## OPcache un drošība: kas spēkā pēc PHP2Shell

OPcache nav drošības rīks, taču tam ir sekas drošībai. Pēc PHP2Shell svarīgi trīs punkti:

1. **Kešatmiņas atiestatīšana nav atjauninājums.** `opcache_reset()` iztīra tikai kešotos skriptus. Interpretators ar ievainojamībām CVE-2026-109618 un CVE-2026-109619 paliek atmiņā, līdz visi procesi ir pārstartēti. Kā to izdarīt, skatiet sadaļā [PHP-FPM un visu darbprocesu pārstartēšana](https://phpsos.de/lv/php2shell/php-fpm-neustart/).
2. **Ievadīts kods var turpināt dzīvot kešatmiņā.** Ja fails tika manipulēts un vēlāk aizstāts, ar izslēgtu laika zīmogu pārbaudi var turpināt izpildīt veco versiju. Pēc tīrīšanas tāpēc obligāti jāpārstartē.
3. **Koplietojamai atmiņai vajadzīga nošķiršana.** Serveros ar vairākiem klientiem palīdz atsevišķi PHP-FPM pūli katrai vietnei, kā arī `opcache.validate_permission` un `opcache.restrict_api`. Direktorijam `opcache.file_cache` jābūt rakstāmam tikai PHP lietotājam.

> **Padoms:**
> Pēc katra atjauninājuma pārbaudiet, vai PHP procesu startēšanas laiks ir vēlāks par atjauninājumu. Pilna OPcache ar augstu trāpījumu līmeni nav pierādījums, ka darbojas jaunais interpretators.

## Kā PHP SOS palīdz konkrēti?

- **Pārbaudīt konfigurāciju:** Mēs nolasām aktīvo OPcache konfigurāciju katram darbības režīmam un salīdzinām to ar jūsu lietojumprogrammu.
- **Nodrošināt izvietošanu:** Mēs ieviešam stingru kārtību kešatmiņas atiestatīšanai un pārstartēšanai, lai neturpinātu darboties vecā koda versija.
- **Nošķirt klientus:** [Servera nostiprināšanas](https://phpsos.de/lv/leistungen/server-haertung/) ietvaros mēs iestatām atsevišķus pūlus, `restrict_api` un piemērotas tiesības.
- **Kontrolēt pēc atjauninājumiem:** Mēs pēc procesu startēšanas laikiem pierādām, ka atjauninātais interpretators patiešām ir aktīvs.


## Biežāk uzdotie jautājumi

**Vai OPcache pēc noklusējuma ir aktīvs?**  
OPcache tiek piegādāts kopā ar PHP kopš PHP 5.5.0, un saskaņā ar rokasgrāmatu ar opcache.enable=1 pēc noklusējuma darbojas, tiklīdz paplašinājums ir ielādēts. Vai tas ir ielādēts, atkarīgs no jūsu pakotnes vai hostinga sniedzēja. Komandrindā OPcache pēc noklusējuma ir izslēgts (opcache.enable_cli=0).

**Kāpēc pēc izvietošanas (deployment) joprojām redzu veco kodu?**  
Visticamāk, OPcache failu izmaiņas pārbauda tikai ar intervāliem vai nemaz. Ar opcache.revalidate_freq tas pēc noklusējuma gaida divas sekundes, ar opcache.validate_timestamps=0 nekad. Tad palīdz tikai kešatmiņas atiestatīšana vai PHP-FPM vai Apache pārstartēšana.

**Vai pēc PHP atjauninājuma pietiek ar opcache_reset()?**  
Nē. opcache_reset() iztīra tikai kešatmiņu ar pārveidotajiem skriptiem. PHP atjauninājums nomaina pašu interpretatoru, un tas ir ielādēts katrā darbojošamies procesā. Tāpēc jāpārstartē visi PHP procesi.

**Vai JIT PHP 8.4 ir ieslēgts?**  
Saskaņā ar rokasgrāmatu opcache.jit kopš PHP 8.4.0 pēc noklusējuma ir iestatīts uz disable, savukārt opcache.jit_buffer_size ir 64M. Iepriekš bija otrādi: jit uz tracing, buferis uz 0. Abos gadījumos JIT bez apzinātas konfigurācijas nav aktīvs.

## Avoti

- [PHP rokasgrāmata: OPcache](https://www.php.net/manual/en/book.opcache.php)
- [PHP rokasgrāmata: OPcache konfigurācija](https://www.php.net/manual/en/opcache.configuration.php)
- [PHP rokasgrāmata: OPcache instalācija](https://www.php.net/manual/en/opcache.installation.php)
- [PHP RFC: JIT](https://wiki.php.net/rfc/jit)
