質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.53%

  • SQL

    2952questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

データベースの仕組みについて

解決済

回答 3

投稿

  • 評価
  • クリップ 6
  • VIEW 618

panjaA

score 57

①select ✳︎ from table名:
で全てのデータを取得中に
②insert into table(a,b,c)values(1,2,3):
で新たなデータが登録された場合
①で取得したデータには②で登録したデータが含まれるのでしょうか?

根本的に勘違いしている可能性があるので、間違っている箇所がありましたらご指摘よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

私の考えも、トランザクション分離レベルによる、です。

ただし私は、Repeatable Read以下のファントムリードが生じる分離レベル(MySQLではRead Committed以下)であれば、①に②がINSERTしCOMMITした結果は含まれうると考えます。ファントムリードが発生するということはレンジロックがとられないので②は①の実行中にロック待ちせず実行可能であり(読み取りロック方式 & ページロックでの衝突や、読み取りロック & ロックエスカレーションが発生しない限り)、またその結果が①の実行中に現れることに関してRepeatable Readの定義の上で禁止もしていないはずだからです。

試しにDB2でCURSORを進めながら横からINSERTしてみましたが、INSERTされた行もSELECTされることを確認しました。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/19 01:33

    はい、仰る通りです。
    初心者マークが付いていたので、複雑な回答より、大枠で捉えてもらった方が良いという思いで回答したのが間違いでした。
    正確には他の方の回答を参照してもらうことにして、私の回答で誤った表現部分は少し暈しておきますw

    キャンセル

  • 2017/08/19 01:40

    トランザクションの話はどうしても複雑になってしまいますね

    キャンセル

  • 2017/08/21 13:17 編集

    他でも書きましたが、MVCCを採用しているDB(Oracleなど)の場合は①の結果はスナップショットとして処理するため、②の処理の影響を受けないように実装されていることが多いです。
    調べたら以下が図解されててわかりやすいように思いました。
    https://techinfoofmicrosofttech.osscons.jp/index.php?DBMSのロック・分離戦略と同時実行制御

    キャンセル

  • 2017/08/21 16:03 編集

    MVCCであっても、記載している通りファントムリードが発生するトランザクション分離レベルであれば影響を受けるはず、というのが私の考えです。①の途中に②が見えるというのは、トランザクション開始後にINSERTされた行が見えるということでファントムリードと実質同じことであると考えます。DB2も今はMVCCを導入しています。

    キャンセル

  • 2017/08/21 17:04

    OracleのようなMVCCではバージョン管理のため、①の処理のバージョンと②の処理のバージョンが異なり、①の結果に②の内容は含まれません。DB2のCS with CCはバージョン管理ではなく、トランザクションログからデータを取得するため後のトランザクション②のデータが①に含まれる可能性があります。のようにファントム・リードとは関係なくDBに実装によって結果は変わってしまいます。

    キャンセル

  • 2017/08/21 18:31

    いろいろ書いてますが、利用者レベルであればトランザクション分離レベルの認識で問題はないという部分は同意です。

    キャンセル

+2

修正(断言的な記述を修正)

トランザクション分離レベルの設定次第です。

採用されているトランザクション分離レベルの多くはREAD COMMITTEDだと思うので、
その場合には、①を開始以降に②が行われても、①の結果には(ほぼ※)含まれません。
※含まれていたとしても、selectの結果行が増えるのと同じ結果になるなら特段の処理は不要だと思います。

但し、実際の環境についてどのトランザクション分離レベルを採用しているかの確認を取られた方が確実です。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/18 08:46 編集

    SELECTの途中でINSERTができ、すでに実行中のSELECTがその影響を受ける分離レベルはたとえばなんでしょうか。yubaさんの回答の通りSELECTが獲得するロックの話で、トランザクション分離レベルはそれには影響しないはずですが。

    デフォルトのトランザクション分離レベルがシリアライザブルになってるRDBMSはたとえば何でしょうか。著名な物のほとんどはシリアライザブル以外になってるはずですが。

    キャンセル

  • 2017/08/18 19:10 編集

    ご指摘ありがとうございます。
    デフォルトのトランザクション分離レベルは、うろ覚えで回答してしまっていたので、修正しました。

    実行中のselect ではトランザクション分離レベルによって、他のトランザクションでの追加・更新・削除により、ファントムリードやダーティリードになる場合があると理解していますが、誤った理解でしょうか?
    また、select 発行しただけでテーブルにロックが掛かるとは初耳なのですが。

    キャンセル

  • 2017/08/18 20:49 編集

    横から失礼します。

    トランザクション分離レベルによってご質問の現象が発生するか否かは私には分かりませんが、
    少なくとも、この手順ではファントムリード・ノンリピータブルリード・ダーティリードは発生しえません。

    なぜなら、
    ファントムリードとノンリピータブルリードは
     1つのトランザクション内で同じ SELECT を【2回】実行したとき、1回目と2回目とで異なる結果になる現象
    で、
    ダーティリードは
     【データを更新するトランザクションを先に】実行し、SELECT 後にロールバックすると発生する現象
    だからです。

    https://en.wikipedia.org/wiki/Isolation_(database_systems)#Read_phenomena

    もし、ご質問の現象が発生するとしても、それは上記3つのケースのいずれでもない何か、ということです。

    キャンセル

  • 2017/08/18 22:43 編集

    Re:KiyoshiMotoki様
    コメントありがとうございます。

    自身の経験では、READ COMMITTEDの場合で、ファントムリードが問題となるような実装となる設計には普通ならないだろうという気がします。
    なぜなら、同一のトランザクション内で同一のselectを発行することが無かったからです。

    質問者様が心配しておられる同一テーブルへの複数回のSELECTの発行による不整合が現実にあり得るかどうかを考えた時、例えば、fetchによる2重ループの内と外で、それぞれAというテーブルを結合したSQLを発行した場合にはファントムリードによる不整合があり得る気がします。

    ダーティーリードについては、「・・・ロールバックすると・・・」そういう対処の実装を行っているDBMSが何なのか把握していません。

    今回質問者様は特定のDBMSに限定しているわけではなかったので
    ANSI/ISO SQL標準上では「更新途中で読取れる」こととなっているので、
    その規格の範囲内ではあり得ることとして考えた方が良いのではと思います。

    あくまで、議論としての発言で、反論という類ではありません。
    配慮の欠けた発言がありましたら、ご容赦下さい。

    キャンセル

  • 2017/08/19 12:27

    トランザクション分離レベルというのは、複数のトランザクションが走る場合に、そのトランザクションの中の個々の操作がトランザクション間でどのように影響するするかを定義したものです。複数のSELECTを行うトランザクションの処理中に別のトランザクションのINSERTが割り込んだ(割り込もうとした)とした時にどうなるか、という話であればトランザクション分離レベルの話ですが、質問のようにSELECTを実行しそのデータを取得中にINSERTをしたらどうなるかというのはトランザクション分離レベルの関知するところではありません。DBの実装によってトランザクション分離レベルの実現をロックで行っている場合にそのことが間接的に影響する可能性はありますが、トランザクション分離レベルによってその動作が直接的に定義されてるわけではありません。

    キャンセル

  • 2017/08/19 14:42 編集

    質問者様が誤解すると嫌なので書きますが、トランザクション分離レベルをDBMSのモード設定と同義に考えておられませんか?
    トランザクション分離レベルは規格であり、DBMSがどのように実現しているかは関係ありません。
    (モード設定以外にも、テーブルロックやfor updateなども組み合わせて初めて実現するなど)
    「SELECTを実行しそのデータを取得中にINSERTをしたらどうなるか」のような場合を含めた振る舞いを規格として定めたものがトランザクション分離レベルです。

    キャンセル

  • 2017/08/19 15:35 編集

    >複数のSELECTを行うトランザクションの処理中に
    >別のトランザクションのINSERTが割り込んだ(割り込もうとした)とした時にどうなるか

    >質問のようにSELECTを実行しそのデータを取得中にINSERTをしたらどうなるか
    の違いが分かりません。

    後者は、質問の意図が、同一のトランザクション内での話だと言われているのですか?
    suzukis様のこの回答への最初のコメントではロックの話をされているので違うとは思いますが。

    キャンセル

  • 2017/08/19 17:28

    > 「SELECTを実行しそのデータを取得中にINSERTをしたらどうなるか」のような場合を含めた振る舞いを規格として定めたものがトランザクション分離レベル

    違います。ここの理解がちがうなら話になりませんね。

    キャンセル

  • 2017/08/19 18:11 編集

    私の認識が間違えているなら、それを正せるだけの情報が欲しかったのですが、違いますの一言だけなのは、この一連の記事が纏まりのないものになるので、非常に残念です。

    キャンセル

  • 2017/08/21 09:50 編集

    横からですが、A, Bとトランザクションがあった場合に、A.参照1→B.追加1→A.参照2と進んだときの参照1と参照2の結果が異なるという定義がファントム・リードです。A.参照1→B.追加1と進んでA.参照1が終わる前にB.追加1が終わった場合の参照1がどうなるかは定義されていません。
    なので、ファントム・リードが起きるトランザクション分離レベルだからといって、参照1に追加1の内容が含まれる現象(ファントム・リードではない何か)が起きるかどうかはDBの実装によることになると思います。
    ようするに、上記の現象(ファントム・リードではない何か)の結果がどうなろうともトランザクション分離レベルには関係がないということになります。

    キャンセル

  • 2017/08/21 10:33

    上はファントム・リードで書きましたが、ダーティ・リード、反復不可能読み取りでも同様です。
    あと、Oracleだと起きません。

    キャンセル

  • 2017/08/21 10:33 編集

    コメントありがとうございます。
    ファントム・リードに対する認識が違うということですね。
    そうやって、記事全体を見返してみると、辻褄があってきます。
    回答に関わっている中で私だけが認識違いだったようです。
    多分、KiyoshiMotoki様のリンク先をよく読めれば(英語だったので殆ど・・・)、認識の過ちに気付いていたのかもしれません。
    精進致しますので、皆様ご容赦下さい。
    特に、suzukis様、KiyoshiMotoki様には深くお詫びします。
    shoko1様、ありがとうございました。

    キャンセル

  • 2017/08/21 10:42 編集

    panjaA様、色々混乱させ、一番ご迷惑をおかけしたたことかと思います。
    お詫び致します。

    キャンセル

0

DB製品によってロックの仕組みは異なるのですが、①のアクセス中にテーブルには読み取りロックがかかります。読み取りロックがかかったオブジェクトに対して別セッションは書き込みアクセスをできないため、②は①が終わるまで待たされることになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/08/18 20:21 編集

    読み取りロック方式はSQL Serverの初期設定で採用してる程度なので断言するような内容ではないと思います。MVCCの方が一般的ではないでしょうか。

    キャンセル

  • 2017/08/18 20:29 編集

    回答ありがとうございます!
    1つ質問してもよろしいでしょうか。

    http://gyouza-daisuki.hatenablog.com/entry/2013/11/19/150838
    上記サイトで下記のような説明があったのですが、今回の私の質問を下記説明通りに考えると①で取得したデータには②で登録したデータが含まれると思います。

    おそらく私が間違っているのはわかっているのですが、どこを勘違いしてるのかがわかりません。
    助けてください!よろしくお願いします。



    ファントムリード

    別のトランザクションで挿入されたデータが見えることにより、一貫性がなくなる現象。

    トランザクションAでレコードをSELECTする。該当レコードがない。
    トランザクションBでレコードをINSERTし、COMMITする。
    トランザクションAでレコードをSELECTする。2でINSERTとしたレコードが取得できる。

    キャンセル

同じタグがついた質問を見る

  • SQL

    2952questions

    SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。