# OPcache selitettynä: PHP:n tavukoodivälimuisti

> OPcache selitettynä: miten PHP:n tavukoodivälimuisti toimii, mitkä asetukset ovat tärkeitä, miksi se tyhjennetään päivitysten jälkeen ja miten sen suojaa.

Lähde: https://phpsos.de/fi/php/opcache/  
Tilanne: 25.10.2026  
Palveluntarjoaja: PHP SOS, PHP-hätäapu ja palvelimen tietoturva. Pikaapu WhatsAppilla: https://wa.me/491736494914?text=Hei%20PHP%20SOS%2C%20tarvitsemme%20apua%20PHP-palvelimemme%20kanssa.%20Yritys%3A%20%E2%80%A6%20Verkkosivusto%3A%20%E2%80%A6

**Lyhyesti:** OPcache on PHP:n sisäänrakennettu tavukoodivälimuisti. Käsikirjan mukaan se tallentaa esikäännettyä tavukoodia jaettuun muistiin, jolloin PHP:n ei tarvitse ladata ja kääntää komentosarjoja uudelleen jokaisella pyynnöllä. Se kuuluu toimitukseen versiosta PHP 5.5.0 lähtien. OPcache nopeuttaa PHP:tä, mutta ei korvaa päivitystä: PHP-korjauksen jälkeen kaikki PHP-prosessit on käynnistettävä uudelleen, välimuistin tyhjennys ei riitä.

## Mitä OPcache tarkalleen tekee?

Jokaisella pyynnöllä PHP:n on luettava komentosarja, pilkottava se ja käännettävä opcode-käskyiksi eli [Zend Enginen](https://phpsos.de/fi/php/zend-engine/) virtuaalikoneen komennoiksi. Sadoista tiedostoista koostuvassa CMS-järjestelmässä se on paljon työtä, joka toistuu jatkuvasti.

OPcache tallentaa tämän käännöksen tuloksen jaettuun muistiin (shared memory). Kaikki PHP-FPM-palvelun worker-prosessit tai kaikki mod_php:tä käyttävät Apache-prosessit käyttävät sitä. Jos tiedosto ei muutu, sen tavukoodia käytetään suoraan uudelleen.

OPcache ladataan Zend-laajennuksena, ei tavallisena laajennuksena:

```ini
; Linux (polku paketista riippuen)
zend_extension=opcache.so
; Windows
; zend_extension=php_opcache.dll
```

Käsikirjan mukaan OPcache tulee ladata ennen Xdebugia, jos molemmat ovat aktiivisia.

On tärkeää tietää, kenelle jaettu muisti kuuluu. PHP-FPM:ssä master-prosessi luo sen, ja tämän palvelun kaikkien poolien kaikki worker-prosessit käyttävät sitä. mod_php:ssä se kuuluu Apachen pääprosessille. Palvelun uudelleenkäynnistys tyhjentää siksi välimuistin kokonaan, mutta yksittäinen uusi worker ei. Komentorivillä ei ole kutsujen yli ulottuvaa jaettua muistia, koska jokainen kutsu on oma prosessinsa; siellä OPcache on oletuksena pois päältä.

Päättäjälle riittää nyrkkisääntö: OPcache on tuotantopalvelimilla lähes aina järkevä, mutta se vaatii selkeän toimintatavan käyttöönotoille ja päivityksille.

## Mitkä OPcache-asetukset ovat tärkeitä?

Seuraavat arvot ovat PHP-käsikirjan konfiguraatiosivulta. Sarake ”Muutettavissa” näyttää, missä asetuksen saa asettaa: `INI_SYSTEM` vain php.ini-tiedostossa tai palvelinkonfiguraatiossa, `INI_ALL` missä tahansa.

| Direktiivi | Oletus | Muutettavissa | Merkitys |
|---|---|---|---|
| `opcache.enable` | 1 | INI_ALL | välimuisti päälle tai pois, ajon aikana vain sammutettavissa |
| `opcache.enable_cli` | 0 | INI_SYSTEM | välimuisti komentoriville |
| `opcache.memory_consumption` | 128 | INI_SYSTEM | jaetun muistin koko megatavuina |
| `opcache.interned_strings_buffer` | 8 | INI_SYSTEM | yhteisten merkkijonojen muisti megatavuina |
| `opcache.max_accelerated_files` | 10000 | INI_SYSTEM | välimuistiin tallennettavien komentosarjojen enimmäismäärä |
| `opcache.validate_timestamps` | 1 | INI_ALL | tarkistaa, onko tiedostoja muutettu |
| `opcache.revalidate_freq` | 2 | INI_ALL | tarkistusväli sekunteina, 0 = jokaisella pyynnöllä |
| `opcache.restrict_api` | tyhjä | INI_SYSTEM | sallii API-funktiot vain tietystä polusta |
| `opcache.validate_permission` | 0 | INI_SYSTEM | tarkistaa tiedosto-oikeudet nykyistä käyttäjää vasten |
| `opcache.validate_root` | 0 | INI_SYSTEM | estää nimikolliosiot chroot-ympäristössä |
| `opcache.file_cache` | tyhjä | INI_SYSTEM | toinen välimuistitaso levyllä |

Tyypillinen tuotantokonfiguraatio voisi näyttää tältä. Tarkistakaa arvot ensin omalla sovelluksellanne:

```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
```

Jos asettaa `opcache.validate_timestamps=0`, saa hieman lisää suorituskykyä. Silloin OPcache ei kuitenkaan enää huomaa muuttuneita tiedostoja lainkaan, ja jokainen käyttöönotto vaatii välimuistin nollauksen tai uudelleenkäynnistyksen.

## Välimuistin tarkkailu ja kohdennettu tyhjennys

OPcachessa on omat funktionsa, muun muassa `opcache_get_status()`, `opcache_get_configuration()`, `opcache_invalidate()` ja `opcache_reset()`. Lyhyt, vain lukeva katsaus täyttöasteeseen:

```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);
```

Usean verkkosivuston palvelimilla ei pidä sallia, että jokainen sovellus voi tyhjentää tai lukea kaikkien muiden välimuistin. Tähän on tarkoitettu `opcache.restrict_api`: vain annetun polun alla olevat komentosarjat saavat kutsua API-funktioita.

## JIT: OPcachen konekoodikääntäjä

PHP 8.0:sta lähtien OPcachessa on JIT-kääntäjä, joka kääntää opcodet konekoodiksi. JIT-RFC:n mukaan se on lähes itsenäinen osa OPcachea ja tallentaa tuottamansa koodin jaetun muistin omalle alueelleen. Sitä ohjataan asetuksilla `opcache.jit` ja `opcache.jit_buffer_size`. Versiosta PHP 8.4.0 lähtien `opcache.jit` on oletuksena `disable`. Milloin JIT kannattaa, selittää artikkeli [JIT ja suorituskyky PHP 8:ssa](https://phpsos.de/fi/php/jit-und-performance/).

## OPcache ja tietoturva: mikä pätee PHP2Shellin jälkeen

OPcache ei ole tietoturvatyökalu, mutta sillä on vaikutuksia tietoturvaan. Kolme asiaa on PHP2Shellin jälkeen tärkeitä:

1. **Välimuistin nollaus ei ole päivitys.** `opcache_reset()` tyhjentää vain välimuistissa olevat komentosarjat. Tulkki, jossa ovat haavoittuvuudet CVE-2026-109618 ja CVE-2026-109619, pysyy muistissa, kunnes kaikki prosessit on käynnistetty uudelleen. Miten se tehdään, kerrotaan sivulla [PHP-FPM ja kaikkien worker-prosessien uudelleenkäynnistys](https://phpsos.de/fi/php2shell/php-fpm-neustart/).
2. **Lisätty koodi voi elää välimuistissa edelleen.** Jos tiedostoa on manipuloitu ja se on myöhemmin korvattu, vanha versio voi aikaleimatarkistuksen ollessa pois päältä jatkaa suorittamista. Puhdistuksen jälkeen uudelleenkäynnistys kuuluu siksi asiaan.
3. **Jaettu muisti vaatii erottelua.** Usean asiakkaan palvelimilla auttavat kullekin verkkosivustolle omat PHP-FPM-poolit sekä `opcache.validate_permission` ja `opcache.restrict_api`. Hakemisto asetukselle `opcache.file_cache` saa olla kirjoitettavissa vain PHP-käyttäjälle.

> **Vinkki:**
> Tarkistakaa jokaisen päivityksen jälkeen, onko PHP-prosessien käynnistysaika päivityksen jälkeinen. Täysi OPcache ja korkea osumasuhde eivät todista, että uusi tulkki on käytössä.

## Miten PHP SOS auttaa konkreettisesti?

- **Konfiguraation tarkistus:** Luemme aktiivisen OPcache-konfiguraation ajotavoittain ja sovitamme sen sovellukseenne.
- **Käyttöönottojen turvaaminen:** Otamme käyttöön kiinteän toimintatavan välimuistin nollaukselle ja uudelleenkäynnistykselle, jotta vanha koodiversio ei jää käyntiin.
- **Asiakkaiden erottelu:** [Palvelimen koventamisen](https://phpsos.de/fi/leistungen/server-haertung/) puitteissa asetamme erilliset poolit, `restrict_api`-asetuksen ja sopivat oikeudet.
- **Tarkistus päivitysten jälkeen:** Osoitamme prosessien käynnistysaikojen avulla, että päivitetty tulkki on todella aktiivinen.


## Usein kysytyt kysymykset

**Onko OPcache oletuksena päällä?**  
OPcache toimitetaan PHP:n mukana versiosta PHP 5.5.0 lähtien, ja käsikirjan mukaan sitä ajetaan oletuksena asetuksella opcache.enable=1, kun laajennus on ladattu. Se, onko laajennus ladattu, riippuu paketistanne tai hosting-yrityksestänne. Komentorivillä OPcache on sen sijaan oletuksena pois päältä (opcache.enable_cli=0).

**Miksi näen käyttöönoton jälkeen yhä vanhan koodin?**  
Todennäköisesti OPcache tarkistaa tiedostomuutokset vain välein tai ei lainkaan. Asetuksella opcache.revalidate_freq se odottaa oletuksena kaksi sekuntia, asetuksella opcache.validate_timestamps=0 ei koskaan. Silloin auttaa vain välimuistin nollaus tai PHP-FPM:n tai Apachen uudelleenkäynnistys.

**Riittääkö opcache_reset() PHP-päivityksen jälkeen?**  
Ei. opcache_reset() tyhjentää vain käännettyjen komentosarjojen välimuistin. PHP-päivitys korvaa itse tulkin, ja se on ladattuna jokaisessa käynnissä olevassa prosessissa. Siksi kaikki PHP-prosessit on käynnistettävä uudelleen.

**Onko JIT päällä PHP 8.4:ssä?**  
Käsikirjan mukaan opcache.jit on versiosta PHP 8.4.0 lähtien oletuksena disable ja opcache.jit_buffer_size on 64M. Aiemmin tilanne oli päinvastainen: jit oli tracing ja puskuri 0. Kummassakin tapauksessa JIT ei ole aktiivinen ilman tietoista konfigurointia.

## Lähteet

- [PHP-käsikirja: OPcache](https://www.php.net/manual/en/book.opcache.php)
- [PHP-käsikirja: OPcachen konfiguraatio](https://www.php.net/manual/en/opcache.configuration.php)
- [PHP-käsikirja: OPcachen asennus](https://www.php.net/manual/en/opcache.installation.php)
- [PHP RFC: JIT](https://wiki.php.net/rfc/jit)
