

Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.

# Membandingkan tingkat isolasi Babelfish dan SQL Server
<a name="babelfish-transaction.examples"></a>

 Di bawah ini adalah beberapa contoh tentang nuansa bagaimana SQL Server dan Babelfish mengimplementasikan tingkat isolasi ANSI. 

**catatan**  
Tingkat isolasi `REPEATABLE READ` dan `SNAPSHOT` sama di Babelfish.
Tingkat isolasi `READ UNCOMMITTED` dan `READ COMMITTED` sama di Babelfish.

Contoh berikut menunjukkan cara membuat tabel dasar untuk semua contoh yang disebutkan di bawah ini:

```
CREATE TABLE employee (
    id sys.INT NOT NULL PRIMARY KEY,
    name sys.VARCHAR(255)NOT NULL,
    age sys.INT NOT NULL
);
INSERT INTO employee (id, name, age) VALUES (1, 'A', 10);
INSERT INTO employee (id, name, age) VALUES (2, 'B', 20);
INSERT INTO employee (id, name, age) VALUES (3, 'C', 30);
```

**Topics**
+ [Babelfish `READ UNCOMMITTED` dibandingkan dengan tingkat isolasi SQL Server `READ UNCOMMITTED`](#babelfish-transaction.examples.unc)
+ [Babelfish `READ COMMITTED` dibandingkan dengan tingkat isolasi SQL Server `READ COMMITTED`](#babelfish-transaction.examples.com)
+ [Babelfish `READ COMMITTED` dibandingkan dengan tingkat isolasi SQL Server `READ COMMITTED SNAPSHOT`](#babelfish-transaction.examples.snapshot)
+ [Babelfish `REPEATABLE READ` dibandingkan dengan tingkat isolasi SQL Server `REPEATABLE READ`](#babelfish-transaction.examples.read)
+ [Babelfish `SERIALIZABLE` dibandingkan dengan tingkat isolasi SQL Server `SERIALIZABLE`](#babelfish-transaction.examples.serialize)

## Babelfish `READ UNCOMMITTED` dibandingkan dengan tingkat isolasi SQL Server `READ UNCOMMITTED`
<a name="babelfish-transaction.examples.unc"></a>

Tabel berikut memberikan rincian tentang pembacaan kotor ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `READ UNCOMMITTED` isolasi di SQL Server dibandingkan dengan implementasi Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `READ UNCOMMITTED` | Ikan babelfish `READ UNCOMMITTED` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;` | `SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;` | Tidak ada | Tidak ada | 
| Idle pada transaksi | `UPDATE employee SET age=0;` | Pembaruan berhasil. | Pembaruan berhasil. | 
| Idle pada transaksi | `INSERT INTO employee VALUES (4, 'D', 40);` | Masukkan berhasil. | Masukkan berhasil. | 
| `SELECT * FROM employee;` | Idle pada transaksi | Transaksi 1 dapat melihat perubahan tanpa komitmen dari transaksi 2. | Sama seperti `READ COMMITTED` di Babelfish. Perubahan tanpa komitmen dari transaksi 2 tidak terlihat oleh transaksi 1.  | 
| Idle pada transaksi | `COMMIT` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Melihat perubahan yang dilakukan oleh transaksi 2. | Melihat perubahan yang dilakukan oleh transaksi 2. | 

## Babelfish `READ COMMITTED` dibandingkan dengan tingkat isolasi SQL Server `READ COMMITTED`
<a name="babelfish-transaction.examples.com"></a>

Tabel berikut memberikan rincian tentang perilaku pemblokiran baca-tulis ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `READ COMMITTED` isolasi di SQL Server dibandingkan dengan implementasi Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `READ COMMITTED` | Ikan babelfish `READ COMMITTED` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `UPDATE employee SET age=100 WHERE id = 1;` | Pembaruan berhasil. | Pembaruan berhasil. | 
| `UPDATE employee SET age = 0 WHERE age IN (SELECT MAX(age) FROM employee);` | Idle pada transaksi | Langkah diblokir hingga transaksi 2 dilakukan. | Transaksi 2 perubahan belum terlihat. Pembaruan baris dengan id = 3. | 
| Idle pada transaksi | `COMMIT` | Transaksi 2 berhasil dilakukan. Transaksi 1 sekarang tidak diblokir dan melihat pembaruan dari transaksi 2. | Transaksi 2 berhasil dilakukan.  | 
| `SELECT * FROM employee;` | Idle pada transaksi | Transaksi 1 memperbarui baris dengan id = 1. | Transaksi 1 memperbarui baris dengan id = 3. | 

## Babelfish `READ COMMITTED` dibandingkan dengan tingkat isolasi SQL Server `READ COMMITTED SNAPSHOT`
<a name="babelfish-transaction.examples.snapshot"></a>

Tabel berikut memberikan rincian tentang perilaku pemblokiran baris yang baru dimasukkan ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `READ COMMITTED SNAPSHOT` isolasi di SQL Server dibandingkan dengan implementasi `READ COMMITTED` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `READ COMMITTED SNAPSHOT` | Ikan babelfish `READ COMMITTED` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | `SET TRANSACTION ISOLATION LEVEL READ COMMITTED;` | Tidak ada | Tidak ada | 
| `INSERT INTO employee VALUES (4, 'D', 40);` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `UPDATE employee SET age = 99;` | Langkah diblokir sampai transaksi 1 dilakukan. Baris yang dimasukkan dikunci oleh transaksi 1. | Diperbarui tiga baris. Baris yang baru dimasukkan belum terlihat. | 
| `COMMIT` | Idle pada transaksi | Berkomitmen sukses. Transaksi 2 sekarang tidak diblokir. | Berkomitmen sukses. | 
| Idle pada transaksi | `SELECT * FROM employee;` | Semua 4 baris memiliki usia = 99. | Baris dengan id = 4 memiliki nilai usia 40 karena tidak terlihat oleh transaksi 2 selama kueri pembaruan. Baris lainnya diperbarui ke age=99.  | 

## Babelfish `REPEATABLE READ` dibandingkan dengan tingkat isolasi SQL Server `REPEATABLE READ`
<a name="babelfish-transaction.examples.read"></a>

Tabel berikut memberikan rincian tentang perilaku pemblokiran baca-tulis ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `REPEATABLE READ` isolasi di SQL Server dibandingkan dengan implementasi `REPEATABLE READ` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `REPEATABLE READ` | Ikan babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| `UPDATE employee SET name='A_TXN1' WHERE id=1;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `SELECT * FROM employee WHERE id != 1;` | Tidak ada | Tidak ada | 
| Idle pada transaksi | `SELECT * FROM employee;` | Transaksi 2 diblokir sampai transaksi 1 dilakukan. | Transaksi 2 berlangsung secara normal.  | 
| `COMMIT` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `SELECT * FROM employee;` | Pembaruan dari transaksi 1 terlihat. | Pembaruan dari transaksi 1 tidak terlihat. | 
| `COMMIT` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `SELECT * FROM employee;` | melihat pembaruan dari transaksi 1. | melihat pembaruan dari transaksi 1. | 

Tabel berikut memberikan rincian tentang perilaku pemblokiran tulis-tulis ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `REPEATABLE READ` isolasi di SQL Server dibandingkan dengan implementasi `REPEATABLE READ` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `REPEATABLE READ` | Ikan babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | Tidak ada | Tidak ada | 
| `UPDATE employee SET name='A_TXN1' WHERE id=1;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `UPDATE employee SET name='A_TXN2' WHERE id=1;` | Transaksi 2 diblokir. | Transaksi 2 diblokir. | 
| `COMMIT` | Idle pada transaksi | Komit berhasil dan transaksi 2 telah diblokir. | Komit berhasil dan transaksi 2 gagal dengan kesalahan tidak dapat membuat serial akses karena pembaruan bersamaan. | 
| Idle pada transaksi | `COMMIT` | Berkomitmen sukses. | Transaksi 2 telah dibatalkan. | 
| Idle pada transaksi | `SELECT * FROM employee;` | Baris dengan id=1 memiliki name='A\_TX2'. | Baris dengan id=1 memiliki name='A\_TX1'. | 

Tabel berikut memberikan rincian tentang perilaku membaca hantu ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `REPEATABLE READ` isolasi di SQL Server dibandingkan dengan implementasi `REPEATABLE READ` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `REPEATABLE READ` | Ikan babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `INSERT INTO employee VALUES (4, 'NewRowName', 20);` | Transaksi 2 berlangsung tanpa pemblokiran. | Transaksi 2 berlangsung tanpa pemblokiran. | 
| Idle pada transaksi | `SELECT * FROM employee;` | Baris yang baru dimasukkan terlihat. | Baris yang baru dimasukkan terlihat. | 
| Idle pada transaksi | `COMMIT` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Baris baru yang dimasukkan oleh transaksi 2 terlihat. | Baris baru yang dimasukkan oleh transaksi 2 tidak terlihat. | 
| `COMMIT` | Idle pada transaksi | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Baris yang baru dimasukkan terlihat. | Baris yang baru dimasukkan terlihat. | 

Tabel berikut memberikan rincian ketika transaksi bersamaan dijalankan dan hasil akhir yang berbeda ketika menggunakan tingkat `REPEATABLE READ` isolasi di SQL Server dibandingkan dengan implementasi `REPEATABLE READ` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `REPEATABLE READ` | Ikan babelfish `REPEATABLE READ` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | Tidak ada | Tidak ada | 
| `UPDATE employee SET age = 100 WHERE age IN (SELECT MIN(age) FROM employee);` | Idle pada transaksi | Transaksi 1 memperbarui baris dengan id 1. | Transaksi 1 memperbarui baris dengan id 1. | 
| Idle pada transaksi | `UPDATE employee SET age = 0 WHERE age IN (SELECT MAX(age) FROM employee);` | Transaksi 2 diblokir karena pernyataan SELECT mencoba membaca baris yang dikunci oleh kueri UPDATE dalam transaksi 1. | Transaksi 2 berlangsung tanpa pemblokiran karena baca tidak pernah diblokir, pernyataan SELECT dijalankan dan akhirnya baris dengan id = 3 diperbarui karena perubahan transaksi 1 belum terlihat. | 
| Idle pada transaksi | `SELECT * FROM employee;` | Langkah ini dilakukan setelah transaksi 1 dilakukan. Baris dengan id = 1 diperbarui oleh transaksi 2 pada langkah sebelumnya dan terlihat di sini. | Baris dengan id = 3 diperbarui oleh Transaksi 2. | 
| `COMMIT` | Idle pada transaksi | Transaksi 2 sekarang tidak diblokir. | Berkomitmen sukses. | 
| Idle pada transaksi | `COMMIT` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Kedua transaksi mengeksekusi pembaruan pada baris dengan id = 1. | Baris yang berbeda diperbarui dengan transaksi 1 dan 2. | 

## Babelfish `SERIALIZABLE` dibandingkan dengan tingkat isolasi SQL Server `SERIALIZABLE`
<a name="babelfish-transaction.examples.serialize"></a>

Tabel berikut memberikan rincian tentang kunci rentang ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `SERIALIZABLE` isolasi di SQL Server dibandingkan dengan implementasi `SERIALIZABLE` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `SERIALIZABLE` | Ikan babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `INSERT INTO employee VALUES (4, 'D', 35);` | Transaksi 2 diblokir sampai transaksi 1 dilakukan. | Transaksi 2 berlangsung tanpa pemblokiran. | 
| Idle pada transaksi | `SELECT * FROM employee;` | Tidak ada | Tidak ada | 
| `COMMIT` | Idle pada transaksi | Transaksi 1 berhasil dilakukan. Transaksi 2 sekarang tidak diblokir. | Transaksi 1 berhasil dilakukan.  | 
| Idle pada transaksi | `COMMIT` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Baris yang baru dimasukkan terlihat. | Baris yang baru dimasukkan terlihat. | 

Tabel berikut memberikan rincian ketika transaksi bersamaan dijalankan dan hasil akhir yang berbeda ketika menggunakan tingkat `SERIALIZABLE` isolasi di SQL Server dibandingkan dengan implementasi `SERIALIZABLE` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `SERIALIZABLE` | Ikan babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | Tidak ada | Tidak ada | 
| Idle pada transaksi | `INSERT INTO employee VALUES (4, 'D', 40);` | Tidak ada | Tidak ada | 
| `UPDATE employee SET age =99 WHERE id = 4;` | Idle pada transaksi | Transaksi 1 diblokir sampai transaksi 2 dilakukan. | Transaksi 1 berlangsung tanpa pemblokiran. | 
| Idle pada transaksi | `COMMIT` | Transaksi 2 berhasil dilakukan. Transaksi 1 sekarang tidak diblokir. | Transaksi 2 berhasil dilakukan. | 
| `COMMIT` | Idle pada transaksi | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Baris yang baru dimasukkan terlihat dengan nilai usia = 99. | Baris yang baru dimasukkan terlihat dengan nilai usia = 40. | 

Tabel berikut memberikan rincian ketika Anda `INSERT` ke dalam tabel dengan kendala yang unik. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `SERIALIZABLE` isolasi di SQL Server dibandingkan dengan implementasi `SERIALIZABLE` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `SERIALIZABLE` | Ikan babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | Tidak ada | Tidak ada | 
| Idle pada transaksi | `INSERT INTO employee VALUES (4, 'D', 40);` | Tidak ada | Tidak ada | 
| `INSERT INTO employee VALUES ((SELECT MAX(id)+1 FROM employee), 'E', 50);` | Idle pada transaksi | Transaksi 1 diblokir sampai transaksi 2 dilakukan. | Transaksi 1 diblokir sampai transaksi 2 dilakukan. | 
| Idle pada transaksi | `COMMIT` | Transaksi 2 berhasil dilakukan. Transaksi 1 sekarang tidak diblokir. | Transaksi 2 berhasil dilakukan. Transaksi 1 dibatalkan dengan kesalahan nilai kunci duplikat melanggar batasan unik. | 
| `COMMIT` | Idle pada transaksi | Transaksi 1 berhasil dilakukan. | Transaksi 1 komit gagal dengan tidak dapat membuat serial akses karena ketergantungan baca atau tulis di antara transaksi. | 
| `SELECT * FROM employee;` | Idle pada transaksi | baris (5, 'E', 50) dimasukkan. | Hanya ada 4 baris. | 

Di Babelfish, transaksi bersamaan yang berjalan dengan Isolation Level serializable akan gagal dengan kesalahan anomali serialisasi jika eksekusi transaksi ini tidak konsisten dengan semua kemungkinan eksekusi serial (satu per satu) dari transaksi tersebut.

Tabel berikut memberikan rincian tentang anomali serialisasi ketika transaksi bersamaan dijalankan. Ini menunjukkan hasil yang diamati ketika menggunakan tingkat `SERIALIZABLE` isolasi di SQL Server dibandingkan dengan implementasi `SERIALIZABLE` Babelfish.


| Transaksi 1 | Transaksi 2 | SQL Server `SERIALIZABLE` | Ikan babelfish `SERIALIZABLE` | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| `UPDATE employee SET age=5 WHERE age=10;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `SELECT * FROM employee;` | Transaksi 2 diblokir sampai transaksi 1 dilakukan. | Transaksi 2 berlangsung tanpa pemblokiran. | 
| Idle pada transaksi | `UPDATE employee SET age=35 WHERE age=30;` | Tidak ada | Tidak ada | 
| `COMMIT` | Idle pada transaksi | Transaksi 1 berhasil dilakukan. | Transaksi 1 dilakukan terlebih dahulu dan mampu melakukan komit dengan sukses. | 
| Idle pada transaksi | `COMMIT` | Transaksi 2 berhasil dilakukan. | Komit transaksi 2 gagal dengan kesalahan serialisasi, seluruh transaksi telah dibatalkan. Coba lagi transaksi 2. | 
| `SELECT * FROM employee;` | Idle pada transaksi | Perubahan dari kedua transaksi terlihat. | Transaksi 2 digulirkan kembali. Hanya transaksi 1 perubahan yang terlihat. | 

Di Babelfish, anomali serialisasi hanya mungkin terjadi jika semua transaksi bersamaan dijalankan pada tingkat isolasi. `SERIALIZABLE` Dalam tabel berikut, mari kita ambil contoh di atas tetapi atur transaksi 2 ke tingkat isolasi `REPEATABLE READ` sebagai gantinya.


| Transaksi 1 | Transaksi 2 | Tingkat isolasi SQL Server | Tingkat isolasi babelfish | 
| --- | --- | --- | --- | 
| `BEGIN TRANSACTION` | `BEGIN TRANSACTION` | Tidak ada | Tidak ada | 
| `SET TRANSACTION ISOLATION LEVEL SERILAIZABLE;` | `SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;` | Tidak ada | Tidak ada | 
| `SELECT * FROM employee;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| `UPDATE employee SET age=5 WHERE age=10;` | Idle pada transaksi | Tidak ada | Tidak ada | 
| Idle pada transaksi | `SELECT * FROM employee;` | Transaksi 2 diblokir sampai transaksi 1 dilakukan. | Transaksi 2 berlangsung tanpa pemblokiran. | 
| Idle pada transaksi | `UPDATE employee SET age=35 WHERE age=30;` | Tidak ada | Tidak ada | 
| `COMMIT` | Idle pada transaksi | Transaksi 1 berhasil dilakukan. | Transaksi 1 berhasil dilakukan. | 
| Idle pada transaksi | `COMMIT` | Transaksi 2 berhasil dilakukan. | Transaksi 2 berhasil dilakukan. | 
| `SELECT * FROM employee;` | Idle pada transaksi | Perubahan dari kedua transaksi terlihat. | Perubahan dari kedua transaksi terlihat. | 