

同じレコードに対して

[code]

    select 
    if 値が前回と違う場合:
      insert or update
      commit
    
[/code]

を行う処理があってこれを並列（べつコネクションで）動かすと  
なぜか毎回複数回実行されてしまいます

値が違う場合にだけ1回新規に書き込まれて  
2回目以降はアップデートがよばれないようにしたいのですが  
かきこんだあとすぐ commit してるんですが  
MySQL ではそういう粒度の管理は不可能なのでしょうか…

あるいは同じクエリに対してはキャッシュが働いてたりするんでしょうか

### 実行環境：

MySQL 5.7 で  
python の pyMySQL スクリプトから sql を叩いています

* * *

### 追記

python の MySQL 関連の部分だけ抜き出すとこんな感じです  
全ステートを取得して現ステートと変化があった場合に処理を行って  
最後にステートをアップデートして同じ処理が２回動かないようにしています

[code]

      mysql = pymysql.connect(
                              host        = settings.db_host,
                              user        = settings.db_user,
                              password    = settings.db_password,
                              db          = settings.db_name,
                              charset     = settings.db_charset
                              )
      try:
        with mysql.cursor() as cursor:
          sql = '''
          SELECT SQL_NO_CACHE user_id, state FROM states
          '''
          cursor.execute(sql)
          results = cursor.fetchall()
          print('select %s' %  results)
    
          if ...: # 変化があった場合
    
            sql = '''
            INSERT INTO states(user_id, state) VALUES (%s, %s)
            ON DUPLICATE KEY UPDATE state = VALUES(state)
            '''
            result = cursor.executemany(sql, [(user_id, states[user_id]) for user_id in states])
            mysql.commit()
            print('update: %s' % states)
      finally:
       mysql.close()
    
[/code]

変化を検出する部分がちょっと長いロジックになってて全部はってもわかりにくいかと思うんですが  
仮にその部分が間違ってたとしても MySQL の値の更新が反映されないのはよくわかりません

MySQL を呼び出す前後でログを出力したところ  
2か所の print で毎回おなじ値が表示されて  
select: A  
update: B  
select: A  
update: B  
:  
select B  
select B

という感じで  
update: のあとに表示された select: の値が違ってるので  
あきらかに update がされてないようにみえます  
しばらくすると唐突に更新が反映されて以降 update がよばれなくなります

かといってエラーが出るわけでもなく  
unique がついてなくて duplicate on update で毎回レコードを作ってるってこともありません

SELECT @@autocommit;  
は 1 になっています

select してから update までにプログラム内でわずかに処理をするので  
割り込まれる可能性はあるんですがその実行時間は0.1秒ないほど一瞬なのに  
アップデートできない表示は数秒～ながいときで数十秒流れ続けます

あと仮に割り込まれたとしてもその場合 print 結果が  
select A  
select A  
update B  
update B  
となると思うんですが

コミット後に  
update B  
が表示されてるにもかかわらずその後  
select A が表示される理由が謎すぎます


CC BY-SA 4.0
2020-01-01T13:48:49.973
61927
2020-01-24T14:19:53.537
2020-01-24T14:19:53.537
question
python mysql pymysql
MySQL select で最新の値を読みたい