序列化的實作
InnoDB對于序列化的實作方式,是通過兩種方式實作的。
第一種,當SELECT語句在一個顯式的事務塊内,如執行表11-9中的編号為1的情況,将施加LOCK_S鎖,根據表11-6(記錄鎖事務鎖相容表)可知,LOCK_S鎖排斥寫鎖,是以序列化隔離級别下隻允許并發地讀取操作,并發寫被禁止,是以實作了可序列化(參見1.2.2節)。相應代碼如下:
ha_innobase::
external_lock(...)
{...
if (lock_type != F_UNLCK) {
...
if (trx->isolation_level ==
TRX_ISO_SERIALIZABLE//
序列化隔離級别&& m_prebuilt->select_lock_type == LOCK_NONE
&& thd_test_options(thd,
OPTION_NOT_AUTOCOMMIT|
OPTION_BEGIN)) { //
且在一個顯式事務塊内部m_prebuilt->
select_lock_type=
LOCK_S; //
加讀鎖,即 'LOCK IN SHARE MODE'm_prebuilt->stored_select_lock_type = LOCK_S;
} //
否則,不加鎖(這一點也很重要)...
} else {
TrxInInnoDB::end_stmt(trx);
DEBUG_SYNC_C("ha_innobase_end_statement");
}
...}
第二種,當SELECT語句不在一個顯式的事務塊内,則通過擷取最新快照(在事務開始的時候,),然後讀取資料。此時,因基于快照的一緻性讀不需要加鎖,是以其加鎖情況對應到了表11-9中的編号2對應的情況。
表11-9 序列化隔離級别加鎖情況
隔離級别 | 編号 | SQL 語句 | 施加的鎖 |
SERIALIZABLE | 1 | BEGIN; S0; | LOCK_S + LOCK_REC_NOT_GAP |
2 | S0; | 沒有鎖 |
說明:
q S0:SELECT * FROM bluesea WHERE c1=2; //使用主鍵索引做WHERE條件
另外,對于FLUSH...WITH READ LOCK語句,序列化隔離級别下也需要加讀鎖LOCK_S,代碼如下:
ha_innobase::
store_lock(
...
if (trx->isolation_level ==
TRX_ISO_SERIALIZABLE) {
m_prebuilt->select_lock_type =
LOCK_S;
m_prebuilt->stored_select_lock_type =
LOCK_S;
} else {
m_prebuilt->select_lock_type = LOCK_NONE;
m_prebuilt->stored_select_lock_type = LOCK_NONE;
}
...
}
與序列化相關的,還有innobase_query_caching_of_table_permitted()函數,序列化隔離級别不允許緩沖查詢。