選択されたクエリにMySQLコミットデータが表示されない


13

コンテキスト:使用されるフレームワークはSpringであり、すべてのクエリはJdbcTemplateで実行されます。Mysqlサーバーのバージョンは5.6.19です。tableでありInnoDB table、デフォルトのようなauto commit分離レベル反復-読み取りが設定されていると。

問題Insertトランザクション内で発生し、select挿入された同じデータを読み取ると、データが表示されません。select実行した後insertとした後、insertトランザクションが持ちますcommited

mysqlでbinログと一般ログを有効にしました。以下の関連ログ

bin-log:

SET TIMESTAMP=1438265764/*!*/;
BEGIN
/*!*/;
# at 249935389
#150730 14:16:04 server id 1  end_log_pos 249935606 CRC32 0xa6aca292    Query   thread_id=40    exec_time=0     error_code=0
SET TIMESTAMP=1438265764/*!*/;
insert into user_geo_loc_latest(user_id, lat, lng) values(x,y,z) on duplicate key update lat=y, lng=z
/*!*/;
# at 249935606
#150730 14:16:06 server id 1  end_log_pos 249936255 CRC32 0x2a52c734    Query   thread_id=40    exec_time=0     error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table(txnid) VALUES ('885851438265675046')
/*!*/;
# at 249936255
#150730 14:16:06 server id 1  end_log_pos 249936514 CRC32 0x6cd85eb5    Query   thread_id=40    exec_time=0     error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table2(x) VALUES (y)
/*!*/;
# at 249936514
#150730 14:16:06 server id 1  end_log_pos 249936545 CRC32 0xceb9ec56    Xid = 9406873
COMMIT/*!*/;

クエリログ

150730 14:16:04    40 Query ...
....
40 Query     select count(*) from table where txnid = '885851438265675046'
                   40 Query     select @@session.tx_read_only
                   40 Query     INSERT INTO table(txnid) VALUES ('885851438265675046')
                   40 Query     select @@session.tx_read_only
                   40 Query     INSERT INTO table2(x) values(y)
                   40 Query     commit
....
150730 14:16:07    36 Query     select pp.*, b.create_date from table pp left join bill b on pp.bill_id = b.bill_id where pp.txnid = '885851438265675046'

奇妙なことに、最初insert(249935389)はトランザクションの一部であってはなりません。これは別個のAPI呼び出しであり、完全に無関係です。それはトランザクションと春の混合である可能性がありますか、ログを間違って読んでいますか?AFAIKは同じスレッド上にあるため、挿入がトランザクション内にあることを意味します。

次の2つinsertsはトランザクションの一部であり、コミットするように見えます。(249936514)。現在、選択クエリ(一般ログの最後のクエリ)はコミット後に実行され、データは表示されません。0行を返します。データを考慮すると、これはどのように起こりcommittedますか またはcommit、スレッド40にないのですか?スレッドIDがないため。

要約すると、2つの質問があります。

  1. BEGINの前にビンログビーイング中にINSERT INTO user_geo_loc、彼らがきた時にトランザクションがビンログに書かれている通り(それは、このトランザクションはすでにコミットしている知っているとして、これは春/ JDBCまたはMySQLでバグですが、単純にこれを行い、(トランザクションの一部ではないです)成功したため、ロールバックされません。

  2. 選択の前にコミットが発生するとします(コミットは14:16:06で、選択は14:16:07にあります)。selectがトランザクションによって挿入された行を返さないのはどうですか?

これは非常に困惑しています。助けていただければ幸いです

注:ビンとクエリログの両方のクエリは、機密情報を削除するために編集されています。しかし、クエリの本質は同じままです

編集:一般的なログとクエリログで更新され、詳細な例があります。


5.5にタグ付けしましたが、5.6に言及しました。どっち?レプリケーションは関係していますか?
リックジェームズ

@RickJames申し訳ありませんが、5.6.19です。質問とbinログの両方の例で質問を更新しました。また、問題はデバッグに気づいた後にのみ、binログをオンにしたレプリケーションは含まれていません。ありがとう
アーメドイオンAxan

おかげで助かります。BEGINまたはが表示されませんSTART TRANSACTION。代わりに、使用していautocommit=0ますか?(開始すること
リックジェームズ

そのため、フレームワーク(スプリング)はトランザクションを管理し、通常autocommit = 0を設定し、最後にコミットします。接続がすでにその状態にあったため、ここではautocommit = 0が表示されないと推測しています。
アーメドイオンアクサン

回答:


3

2番目の質問について仮説を立てようとします。

選択の前にコミットが発生するとします(コミットは14:16:06で、選択は14:16:07にあります)。selectがトランザクションによって挿入された行を返さないのはどうですか?

トランザクションはSpringによって管理されます。そのため、selectスプリングを実行する前にを発生させstart transactionたり、別のクエリを実行するために既に接続を使用したりする可能性があります。

テーブルへの挿入をシミュレートする最初のセッションを開始しますt

session1> create table t (i int auto_increment primary key);
Query OK, 0 rows affected (0,32 sec)

session1> insert into t values();
Query OK, 1 row affected (0,00 sec)

session1> select * from t;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

session1> start transaction;
Query OK, 0 rows affected (0,00 sec)

session1> insert into t values();
Query OK, 1 row affected (0,00 sec)

autocommit0に設定された新しいセッションsession2を作成します。この新しいセッションでは、selectの実行時にトランザクションが暗黙的に開始されます。

session2> set autocommit = 0;
Query OK, 0 rows affected (0,00 sec)

session2> select * from t;  -- this starts a transaction
+---+
| i |
+---+
| 1 |
+---+
1 rows in set (0,00 sec)

session1に移動して、挿入をコミットします。

session1> commit;

次に、再びsession2に移動します。

session2> select * from t;
+---+
| i |
+---+
| 1 |
+---+
1 row in set (0,00 sec)

Session2は、挿入されたばかりの行を見ることができません。commitsession2でa が発生した場合、session1に新しい行が挿入されていることがわかります

session2> commit
1 row in set (0,00 sec)

session2> select * from t;
+---+
| i |
+---+
| 1 |
| 2 |
+---+
2 rows in set (0,00 sec)

一般的なログは次のようになります。

150804 14:04:10     2 Query select * from t

150804 14:04:30     1 Query start transaction
150804 14:04:39     1 Query insert into t values ()
150804 14:04:44     1 Query commit
150804 14:04:51     2 Query select * from t

150804 14:05:07     2 Query commit
150804 14:05:10     2 Query select * from t

最初の行はセッション2に関連しています。これは、セッション2がトランザクションを開くときです。

これがあなたの場合に起こるかどうかはわかりません。connection_id 36が他のクエリに使用されている場合、一般ログで確認できます。お知らせください。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.