OracleDBのselect for updateってどのへんのレコードまでロックしよる?

結合したテーブルの該当行までロックしよる?

select j.*, h.*
from jobs j, job_history h
where j.job_id = h.job_id
and j.job_id = 'ST_CLERK'
for update;
JOB_ID        JOB_TITLE        MIN_SALARY MAX_SALARY EMPLOYEE_ID START_DA END_DATE JOB_ID        DEPARTMENT_ID
------------- ---------------- ---------- ---------- ----------- -------- -------- ------------- -------------
ST_CLERK      Stock Clerk            2008       5000         114 06-03-24 07-12-31 ST_CLERK                 50
ST_CLERK      Stock Clerk            2008       5000         122 07-01-01 07-12-31 ST_CLERK                 50

ロックをかけて、他方で結合させた行にロックをかけにいってみる。

select * from jobs where job_id = 'ST_CLERK' for update nowait;
select * from jobs where job_id = 'ST_CLERK' for update nowait
              *
行1でエラーが発生しました。:
ORA-00054: リソース・ビジー。NOWAITが指定されているか、タイムアウトしました
select * from job_history where job_id = 'ST_CLERK' for update nowait;
select * from job_history where job_id = 'ST_CLERK' for update nowait
              *
行1でエラーが発生しました。:
ORA-00054: リソース・ビジー。NOWAITが指定されているか、タイムアウトしました

結論:結合したテーブルの該当業行までロックしよる。

サブクエリの該当行までロックしよる?

さすがにロックしないでしょ。。

job_historyが存在するjobを拾ってくるsqlで試す。

select * from jobs j
where exists(select 1 from job_history h where j.job_id = h.job_id)
for update;
JOB_ID         JOB_TITLE                      MIN_SALARY MAX_SALARY
-------------- ------------------------------ ---------- ----------
AD_ASST        Administration Assistant             3000       6000
AC_MGR         Accounting Manager                   8200      16000
AC_ACCOUNT     Public Accountant                    4200       9000
SA_MAN         Sales Manager                       10000      20080
SA_REP         Sales Representative                 6000      12008
ST_CLERK       Stock Clerk                          2008       5000
IT_PROG        Programmer                           4000      10000
MK_REP         Marketing Representative             4000       9000

ロックをかけて、他方でサブクエリで引っ張ってきた行にロックをかけにいってみる。サブクエリでしか使っていないjob_historyの該当行にはロックがかかっていない。

select * from jobs where job_id = 'AD_ASST' for update nowait;
select * from jobs where job_id = 'AD_ASST' for update nowait
              *
行1でエラーが発生しました。:
ORA-00054: リソース・ビジー。NOWAITが指定されているか、タイムアウトしました
select * from job_history where job_id = 'AD_ASST' for update nowait;
EMPLOYEE_ID START_DA END_DATE JOB_ID               DEPARTMENT_ID
----------- -------- -------- -------------------- -------------
        200 95-09-17 01-06-17 AD_ASST                         90

結論:サブクエリの該当行まではロックしない。そりゃね。だって最終的にselectするものじゃないもんね。

(^ω^)にこっ