Kilitler, SQL çalıştırma sırasında işlem yalıtımını sağlar. Hologres hem Frontend (FE) hem de Backend (BE) kilitlerini kullanır; her birinin farklı türleri, kapsamları ve çakışma davranışları vardır. Bu konuda bu kilitlerin çalışma şekli ve kilit kaynaklı sorunların nasıl giderileceği açıklanmaktadır.
Arka Plan
Hologres'te bir sorgu başlatıldığında aşağıdaki şekilde gösterilen yolu izler.
Frontend sorguyu ayrıştırır, Sorgu Motoru bir yürütme planı oluşturur ve Depolama Motoru verileri okur. Bu süreçte iki tür kilit devreye girer.
-
Frontend (FE) kilitleri
Frontend erişim katmanıdır ve PostgreSQL protokolüyle uyumludur; bu nedenle kilitleri de bazı PostgreSQL kilitleriyle uyumludur. FE kilitleri FE meta verilerini yönetir.
-
Backend (BE) kilitleri
BE, Sorgu Motoru ve Sabit Plan'ı ifade eder. Depolama Motorunun şemasını ve verilerini yöneten kendi Hologres kilitlerini kullanır.
Kilit davranışı değişiklikleri
-
Hologres V2.0 sürümünden itibaren Frontend'de (FE) kilitsiz bir mekanizma varsayılan olarak etkindir. Bu, aynı tablo üzerinde bir DDL ifadesi ile bir DQL ifadesi arasında bir çakışma oluşursa (örneğin, Tablo A üzerinde bir DDL işlemi devam ederken yeni bir sorgu gönderilirse) yeni DQL isteğinin hemen başarısız olacağı anlamına gelir. Yeni DQL isteklerinin hemen başarısız olması yerine kilidin serbest bırakılmasını beklemesine izin vermek için GUC parametresini devre dışı bırakın:
ALTER database <db_name> SET hg_experimental_disable_pg_locks = off; Hologres V2.1 sürümünden itibaren, birincil anahtarı olmayan bir tabloya toplu veri yükleme işlemi, tablo düzeyinde bir kilit yerine yalnızca satır düzeyinde bir kilit alacak şekilde optimize edilmiştir.
Kilit türleri
-
FE kilitleri
Hologres erişim katmanı olan Frontend, PostgreSQL ile uyumludur; bu nedenle bu katmandaki kilitler de PostgreSQL uyumludur. PostgreSQL, eşzamanlı veri erişimini kontrol etmek için üç kilit modu sunar: tablo düzeyinde kilitler, satır düzeyinde kilitler ve tavsiye kilitleri. Hologres, tablo düzeyinde kilitler ve tavsiye kilitleriyle uyumludur.
NotHologres açık kilitlemeyi veya tavsiye kilitleriyle ilgili UDF'leri desteklemez.
-
Tablo düzeyinde kilitler
-
Modlar
Tablo düzeyinde kilit, tüm tablo üzerinde alınan bir kilittir. Modlar aşağıdaki gibidir.
Kilit modu
Açıklama
Not
ACCESS SHARE
SELECTkomutu, başvurulan tablolar üzerinde bu modda bir kilit alır.Yok
ROW SHARE
Yalnızca
SELECT FOR UPDATEveSELECT FOR SHAREkomutları hedef tablo üzerinde bu kilidi alır. Hedef olmayan tablolar (JOIN içindeki diğer tablolar gibi) yalnızca ACCESS SHARE kilidi alır.Hologres
SELECT FOR UPDATEveSELECT FOR SHAREkomutlarını desteklemediğinden bu kilit modu geçerli değildir.ROW EXCLUSIVE
UPDATE,DELETEveINSERTgibi verileri değiştiren DML komutları bu kilidi alır.Bu durum BE kilitleriyle birlikte değerlendirilmelidir.
SHARE UPDATE EXCLUSIVE
VACUUMile eşzamanlı şema değişiklikleri arasındaki çakışmaları önleyen bir kilittir. Aşağıdaki komutlar bu kilidi alır.-
lazy VACUUM(Vacuum Fulldeğil). -
ANALYZE. -
CREATE INDEX CONCURRENTLY.NotHologres bu komutu çalıştırdığında
SHARE UPDATE EXCLUSIVEkilidi almaz. Bunun yerine, eşzamanlı olmayanCREATE INDEXkomutuna benzer şekildeSHAREkilidi alır. -
CREATE STATISTICS(Hologres tarafından desteklenmez). -
COMMENT ON. -
ALTER TABLE VALIDATE CONSTRAINT(Hologres tarafından desteklenmez). -
ALTER TABLE SET/RESET (storage_parameter). Hologres yalnızca bu komutu kullanarak kendi genişletilmiş özelliklerini ve yerel PostgreSQLautovacuum_enabledözelliğini ayarlamayı destekler. Bu özelliklerin ayarlanması herhangi bir tablo kilidi almaz. Diğer bazı yerleşik PostgreSQL depolama parametrelerinin değiştirilmesi bu kilidi alır. Daha fazla bilgi için bkz. ALTER TABLE. -
ALTER TABLE ALTER COLUMN SET/RESET options. -
ALTER TABLE SET STATISTICS(Hologres tarafından desteklenmez). -
ALTER TABLE CLUSTER ON(Hologres tarafından desteklenmez). -
ALTER TABLE SET WITHOUT CLUSTER(Hologres tarafından desteklenmez).
ANALYZEkomutuna odaklanın.SHARE
Yalnızca eşzamanlı olmayan
CREATE INDEXbu kilidi alır.NotHologres'te JSON dizini oluşturmak bu kilidi alır.
(JSON ile ilgili dizinler oluşturmak için)
CREATE INDEXkomutuna odaklanın.SHARE ROW EXCLUSIVE
Eşzamanlı veri değişikliklerini önleyen bir kilittir. Aşağıdaki komutlar bu kilidi alır.
-
CREATE COLLATION(Hologres tarafından desteklenmez). -
CREATE TRIGGER(Hologres tarafından desteklenmez). -
Bazı
ALTER TABLEkomutları.-
DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER(Hologres tarafından desteklenmez). -
ADD table_constraint(Hologres tarafından desteklenmez).
-
Hologres bu kilidi alan komutları desteklemediğinden bu kilit modu geçerli değildir.
EXCLUSIVE
Yalnızca
REFRESH MATERIALIZED VIEW CONCURRENTLYkomutu bu kilidi alır.Hologres
REFRESH MATERIALIZED VIEW CONCURRENTLYkomutunu desteklemediğinden bu kilit modu geçerli değildir.ACCESS EXCLUSIVE
Tamamen özel erişim için gerekli olan ve diğer tüm kilitlerle çakışan bir kilittir. Aşağıdaki komutlar bu kilidi alır.
-
DROP TABLE -
TRUNCATE TABLE -
REINDEX(Hologres tarafından desteklenmez). -
CLUSTER(Hologres tarafından desteklenmez). -
VACUUM FULL -
REFRESH MATERIALIZED VIEW (CONCURRENTLY olmadan)(Hologres tarafından desteklenmez). -
LOCK: Açık LOCK komutu. Belirli bir kilit türü belirtilmezse bu kilit varsayılan olarak alınır. (Hologres tarafından desteklenmez). -
ALTER TABLE: Yukarıda bahsedilen belirli kilitleri alanALTER TABLEformları dışında, diğerALTER TABLEformları varsayılan olarak bu kilidi alır.
Bu kritik bir kilittir. Hologres'teki DDL işlemleri bu kilidi alır ve bu kilit diğer tüm kilit türleriyle çakışır.
-
-
Zaman aşımı
FE kilitlerinde varsayılan bir zaman aşımı yoktur. Aşırı uzun kilit bekleme sürelerini önlemek için açıkça bir zaman aşımı ayarlamanız gerekir. Bkz. Sorguları Yönetme.
-
Çakışma ilişkileri
Aşağıdaki tabloda kilit modları arasındaki çakışma ilişkileri gösterilmektedir. Çakışma, bir işlemin diğerinin kilidini serbest bırakmasını beklemesi gerektiği anlamına gelir.
Notçakışma olmadığını gösterir. çakışma olduğunu gösterir.
İstenen kilit modu
ACCESS SHARE
ROW SHARE
ROW EXCLUSIVE
SHARE UPDATE EXCLUSIVE
SHARE
SHARE ROW EXCLUSIVE
EXCLUSIVE
ACCESS EXCLUSIVE
ACCESS SHARE
ROW SHARE
ROW EXCLUSIVE
SHARE UPDATE EXCLUSIVE
SHARE
SHARE ROW EXCLUSIVE
EXCLUSIVE
ACCESS EXCLUSIVE
-
-
Tavsiye kilidi
Tavsiye kilitleri uygulama tanımlı anlamlara sahiptir. Çoğu Hologres iş senaryosunda bunlara ekstra dikkat etmeniz gerekmez.
-
-
BE kilitleri
-
Kategoriler
Hologres'te BE Kilitleri aşağıdaki gibi kategorilere ayrılır.
Kilit kategorisi
Kilitlere giriş
Exclusive(X)Bir işlem
DELETE,INSERTveyaUPDATEgibi DML komutlarıyla verileri değiştirmesi gerektiğinde özel kilit (veya mutex kilit) alınır. Kaynak üzerinde başka paylaşımlı veya özel kilit yoksa özel kilit verilebilir. Alındıktan sonra o kaynak üzerine başka kilit konulamaz.
Shared(S)Bir işlem verileri okuması gerektiğinde paylaşımlı kilit istenir ve bu durum diğer işlemlerin okunan verileri değiştirmesini engeller. Aynı kaynak üzerinde birden fazla paylaşımlı kilit bir arada bulunabilir; kaynağı değiştirmedikleri için DQL komutlarının eşzamanlı çalışmasına izin verir.
Intent(I)Niyet kilidi hiyerarşik bir kilit yapısını belirtir ve aynı kaynak üzerinde birden fazla niyet kilidinin bir arada bulunmasına olanak tanır. Bir niyet kilidi alındıktan sonra o kaynak için artık özel kilit verilemez. Örneğin, bir işlem bir satır üzerinde özel kilit istediğinde tablo üzerinde de bir niyet kilidi alır ve bu durum diğer işlemlerin tablo üzerinde özel kilit almasını engeller.
-
Zaman aşımı
BE Kilitleri için varsayılan zaman aşımı 5 dakikadır.
-
Çakışma ilişkisi
BE kilitleri için çakışma ilişkileri aşağıdaki gibidir. Çakışma, bir işlemin diğerinin kilidini serbest bırakmasını beklemesi gerektiği anlamına gelir.
Notçakışma olmadığını gösterir. çakışma olduğunu gösterir.
İşlem
DROP
ALTER
SELECT
UPDATE
DELETE
INSERT (INSERT ON CONFLICT dahil)
DROP
ALTER
SELECT
UPDATE
DELETE
INSERT (INSERT ON CONFLICT dahil)
-
Kilit kapsamları
Kilit kapsamı kategoriye göre değişir.
-
FE kilitleri
FE kilitleri yalnızca tablo nesnelerini etkiler, tablo verilerini etkilemez. Bir kilit ya alınır ya da engellenir. Engellenmesi bir kilit çakışması olduğunu gösterir; yani işlem kilidi beklemektedir.
-
BE kilitleri
BE kilitleri tablo verilerini veya şemayı etkiler. Kapsamları şöyledir:
Tablo verisi kilitleri: Bir tablodaki tüm veriler üzerinde kilit alır. Birden fazla görev tarafından eşzamanlı olarak alınması kilit bekleme gecikmelerine neden olabilir.
Satır verisi kilidi: Tüm bir satırı kilitler ve daha yüksek yürütme verimliliği sağlar. Sabit Plan ile hızlandırılan sorgular satır verisi kilitlerini veya tablo şema kilitlerini kullanır.
-
Tablo şema kilidi: Tablonun şemasını kilitler. Tablo şemasını okuması veya değiştirmesi gereken işlemler tarafından alınır. Çoğu işlem bir şema kilidi alır. Mevcut şema kilit türleri:
SchX: Şema Özel Kilidi, DDL ifadeleri için kullanılır. Şu anda yalnızca
DROP TABLEkomutunu destekler.SchU: Şema Güncelleme Kilidi, tablo yapısını değiştiren DDL ifadeleri için kullanılır;
ALTER TABLEveset_table_propertykomutlarını içerir.SchE: Şema Varlık Kilidi, okuma ve yazma işlemleri sırasında bir tablonun silinmesini önlemek için DML ve DQL ifadeleri tarafından kullanılır.
NotSchU, DDL kilitleri için ayrıntılı kontrol sağlar ve
ALTER TABLEişlemleri sırasında DQL'nin beklemeden normal çalışmasına olanak tanır. SchX, en kaba granülerlikte DDL özel kilididir ve bunun için tüm DDL, DML ve DQL işlemlerinin beklemesi gerekir.Bir sorgunun başlaması uzun sürüyorsa BE kilitlerini bekliyor olabilir.
Hologres'teki yaygın komutlar için kilit kapsamları aşağıdaki gibidir. ifadesi, işlemin belirtilen kilidi aldığını gösterir.
Sabit Plan kullanmayan yazma, güncelleme ve silme işlemleri Bulkload işlemleri olarak kabul edilir.
CREATE INDEXkomutu, JSON ile ilgili dizinlerin oluşturulmasını ifade eder.DDL komutları
CREATE,DROP,ALTERvb. işlemleri içerir.
|
İşlem / Kilit kapsamı |
Tablo düzeyinde kilit |
Tablo verisi kilidi |
Satır verisi kilidi |
Tablo şema kilidi |
|
CREATE |
|
Yok |
||
|
DROP |
Not
|
Yok |
Yok |
Not
Diğer tüm işlemlerle çakışır. |
|
ALTER |
Not
|
Yok |
Yok |
Not
Tablo Şema Kilidi tutulurken tabloda |
|
SELECT |
Not
Tablo kilidi tutulurken tabloda |
Yok |
Yok |
Not
|
|
INSERT (INSERT ON CONFLICT dahil) |
Not
|
Not
Bulkload, Sabit Plan ile çakışır. |
İşlem Sabit Plan aracılığıyla gerçekleştirilirse satır verisi kilidi alınır. Hologres V2.1 sürümünden itibaren, birincil anahtarı olmayan bir tablo için bulkload da yalnızca satır verisi kilidi alır. Not
|
Not
DDL ve DML ile çakışır. |
|
UPDATE |
Not
Bu kilit |
Not
DDL ve DML ile çakışır. |
||
|
DELETE |
Not
Bu kilit |
Not
DDL ve DML ile çakışır. |
||
İşlemle ilgili kilit davranışı
Hologres şu anda yalnızca DDL için açık işlemleri destekler. Saf DML işlemlerini veya karışık DDL ve DML işlemlerini desteklemez.
Hologres iç içe alt işlemleri desteklemez.
-
Saf DML işlemleri sözdizimsel olarak kabul edilse de atomik commit ve geri alma işlemlerini gerçekten desteklemez.
Aşağıdaki DML örneğinde,
INSERTbaşarılı olsa bile sonrakiUPDATEbaşarısız olursa eklenen veriler geri alınmaz.begin; insert into t1(id, salary) values (1, 0); update t1 set salary = 0.1 where id = 1; commit; -
Saf DDL işlemleri beklendiği gibi çalışır.
İşlemdeki herhangi bir DDL komutu başarısız olursa tüm işlem geri alınır. Örneğin, aşağıdaki kodda
ALTERkomutu başarısız olursa öncekiCREATEveDROPişlemleri geri alınır.begin; create table t1(i int); drop table if exists t2; alter table t1 add column n text; commit; -
DDL ve DML komutlarının karışımını içeren işlemler yasaktır.
Aşağıdaki örnekte, bir işlem hem DDL hem de DML komutları içerdiğinde DML komutu hata bildirir.
begin; create table t1(i int); update t1 set i = 1 where i = 1; -- DML statement error ERROR: UPDATE in ddl transaction is not supported now. -
Açık bir işlemdeki herhangi bir komut tarafından alınan kilitler, yalnızca tüm işlem sonlandığında (commit veya rollback ile) serbest bırakılır.
Aşağıdaki örnekte, bir üst tablo üzerindeki
ALTERişlemi hem üst tablo (login_history) hem de alt tablo (login_history_202001) üzerindeACCESS EXCLUSIVEkilitleri alır. Bu kilitler komut tamamlandıktan hemen sonra serbest bırakılmaz. SonCOMMITyürütülene kadar (başarılı veya başarısız olmasından bağımsız olarak) tutulur.COMMITyürütülmezse kilitler süresiz olarak tutulur ve bu tablo üzerindeki diğer tüm DDL işlemleri engellenir ve hata bildirir.-- suppose we have three tables create table temp1(i int, t text); create table login_history(ds text, user_id bigint, ts timestamptz) partition by list (ds); create table login_history_202001 partition of login_history for values in ('202001'); begin; alter table login_history_s1 add column user_id bigint; drop table temp1; create table tx2(i int); commit;
FE kilitlerini sorun giderme
FE kilitlerini kontrol etmek ve çözmek için şu adımları izleyin:
-
Bir sorgu uzun sürüyorsa sorgunun bir kilit bekleyip beklemediğini görmek için
wait_event_typealanını kontrol edin.Aşağıdaki komut örneğinde sonuçtaki
wait_event_typealanıLockise sorgunun bir FE kilidi beklediğini gösterir.-- Hologres V2.0 and later: select query,state,query_id,transaction_id,pid,wait_event_type,wait_event,running_info,extend_info FROM hg_stat_activity where query_id = 200640xxxx; -- The following result is returned: ----------------+---------------------------------------------------------------- query | drop table test_order_table1; state | active query_id | 200640xxxx pid | 123xx transaction_id | 200640xxxx wait_event_type | Lock wait_event | relation running_info | {"current_stage":{"stage_duration_ms":47383,"stage_name":"PARSING"},"fe_id":1,"warehouse_id":0}+ | extend_info | {} + -- Hologres V1.3 and earlier: select datname, pid, application_name, wait_event_type, state,query_start, query from pg_stat_activity where backend_type in ('client backend'); -- The following result is returned: ----------------+---------------------------------------------------------------- datname | holo_poc pid | 321xxx application_name | PostgreSQL JDBC Driver wait_event_type | lock state | active query_start |2023-04-20 14:31:46.989+08 query | delete from xxx -
Kilit sahibini görüntüleyin.
Sözdizimi:
select * from pg_locks where pid = <pid>;pid değerini 1. Adımda döndürülen
piddeğeriyle değiştirin. -
Kilidi hangi işlemin tuttuğunu belirleyin.
2. Adımdaki sonuç mevcut sorgunun bir kilit beklediğini gösteriyorsa tablonun
oid(Object ID) değerini kullanarak üzerinde kilit tutan işlemi bulmak için aşağıdaki komutu kullanın.grantedsütunundakit(true) değeri bir işlemin kilidi tuttuğunu gösterir.-- Query the process that holds the table lock. select pid from pg_locks where relation = <OID> and granted = 't'; -
Kilidi tutan sorguyu belirleyin.
3. Adımın sonucundaki PID'yi kullanarak kilidi tutan sorguyu bulmak için aşağıdaki komutu çalıştırın.
select * from pg_stat_activity where pid = <PID>; -
Kilidi serbest bırakın.
Sorguyu sonlandırmak ve kilidi serbest bırakmak için aşağıdaki komutu çalıştırın.
select pg_cancel_backend(<pid>);
BE kilitlerini sorun giderme
hg_stat_activity görünümündeki be_lock_waiters alanı veri içeriyorsa sorgu bir kilit tutuyor veya bir BE kilidi tarafından engelleniyor demektir. Sorunu gidermek için şu adımları izleyin.
hg_stat_activity yalnızca Hologres V2.0 ve sonraki sürümlerde desteklenir.
-
Senaryo 1: Geçerli sorgu bir kilit tutuyor ve diğer sorgular bunun serbest bırakılmasını bekliyor.
Kilit tutan sorguyu ve engellenen sorguları görüntüleyin:
select query_id, transaction_id, ((extend_info::json)->'be_lock_waiters'->>0)::text as be_lock_waiters FROM hg_stat_activity as h where h.state = 'active' and ((extend_info::json)->'be_lock_waiters')::text != ''; -- The following result is returned: ----------------+------------------ query_id | 10005xxx transaction_id | 10005xxx be_lock_waiters | 13235xxx -
Senaryo 2: Hangi sorgunun geçerli sorguyu engellediğini kontrol edin.
Geçerli sorgunun beklediği kilidi hangi sorgunun tuttuğunu bulun.
select query_id, transaction_id, ((extend_info::json)->'be_lock_waiters')::text as be_lock_waiters FROM hg_stat_activity as h where h.state = 'active' and ((extend_info::jsonb)->'be_lock_waiters')::jsonb ? '10005xxx'; -[ RECORD 1 ]---+------------------------------------------ query_id | 200740017664xxxx transaction_id | 200740017664xxxx be_lock_waiters | ["200640051468xxxx","200540035746xxxx"]
Yaygın hatalar ve çözümler
-
Hata:
internal error: Cannot acquire lock in time, current owners: [(Transaction =302xxxx, Lock Mode = SchS|SchE|X)].Olası neden: Sorgunuz bir BE kilidini 5 dakika bekledikten sonra zaman aşımına uğradı. Başka bir sorgu aynı tablo üzerinde çakışan bir kilit tutuyor (bu durumda SchS, SchE ve Exclusive kilitlerinin bir kombinasyonu).
Çözüm: Engelleyen sorguyu bulun ve sonlandırın. Hata mesajındaki işlem kimliği olan
Transaction =302xxxxengelleyen sorgu kimliğidir. İşlemi tanımlamak ve yönetmek için bu sorgu kimliğini yavaş sorgu günlüğünde veya etkin sorgular görünümünde arayın.
-
Hata:
ERROR: The schema version update timed out because the server's current version (xxx) is older than the requested version (yyy).Olası neden: Bir DDL ifadesi önce şema sürümünü FE'de günceller. Depolama Motoru değişikliği uygulamadan önce yeni bir sorgu gelirse sorgu beklemek zorunda kalır. Bu bekleme 5 dakikalık zaman aşımını aşarsa sorgu başarısız olur.
-
Çözüm:
Kilidi tutan DDL işlemini sonlandırın ve sorgunuzu yeniden çalıştırın.
Sorun devam ederse senkronizasyonu zorlamak için örneği yeniden başlatın.
-
Hata:
The requested table name: xxx (id: 10, version: 26) mismatches the version of the table (id: 10, version: 28) from server.Olası neden: Bir DDL işleminden sonra Depolama Motoru sürümünü günceller ancak bu değişikliğin tüm FE düğümlerine çoğaltılması gerekir. Sorgunuz Depolama Motorundaki en son tablo sürümüyle henüz senkronize olmamış bir FE düğümüne bağlandığında bu hata oluşur.
-
Çözüm:
Sorguyu birkaç kez yeniden deneyin. Güncellenmiş bir FE düğümüne bağlandığınızda sorun genellikle çözülür.
Birkaç dakika boyunca yeniden deneme işe yaramazsa tutarsız durumu temizlemek için örneği yeniden başlatın.
-
Hata:
internal error: Cannot find index full ID: 86xxx (table id: 20yy, index id: 1) in storages or it is deleting!.Olası neden: Bir DML işlemi (
SELECTveyaDELETEgibi) bir tabloya erişmeye çalışırken üzerindeDROP TABLEveyaTRUNCATE TABLEkomutu çalışıyorsa bu hata oluşur. DML sorgusu DDL kilidinin serbest bırakılmasını bekler ancak çalıştırıldığında tablo veya dizini zaten silinmiş olur.Çözüm: Üzerinde
DROPveyaTRUNCATEkomutlarını çalıştırmadan önce bir tablo üzerinde çalışan başka sorgu olmadığından emin olun. Eşzamanlı erişimi önlemek için DDL ve DML işlemlerini koordine edin.