无法看到MySQL提交的数据来选择查询


13

上下文:使用的框架是Spring,所有查询都使用JdbcTemplate运行。Mysql Server版本是5.6.19。和tableInnoDB table,默认设置为,并且设置了auto commit隔离级别可重复读取。

问题Insert在事务内部发生的事情和select读取相同插入数据的事务看不到该数据。在select运行后,insert之后的insert交易都有commited

我已经启用bin日志以及mysql中的常规日志。以下相关日志

二进制日志:

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'

奇怪的是,First insert(249935389)根本不应该成为交易的一部分。这是一个单独的API调用,完全不相关。可能是弹簧将其与事务混合在一起,还是我在读取错误的日志?AFAIK,因为它在同一线程上,这意味着插入在事务中。

接下来的两个inserts是事务的一部分,看起来像提交了。(249936514)。现在,选择查询(一般日志中的最后一个查询)在提交后运行,并且看不到数据。它返回0行。考虑到数据是committed怎么发生的?还是commit不在线程40上?由于它没有线程ID。

总而言之,我有两个问题。

  1. 是否BEGIN在二进制日志之中之前INSERT INTO user_geo_loc(这是不交易的一部分),这与春季/ JDBC或MySQL错误简单地做到这一点,因为它知道这个交易已经承诺(如交易被写入时,他们已经以BINLOG成功),因此永远不会回滚。

  2. 给定提交发生在select之前(commit在14:16:06且select在14:16:07),那么select如何不返回事务插入的行呢?

这非常令人困惑。任何帮助,将不胜感激

注意:bin和查询日志中的查询均已编辑,以删除敏感信息。但是查询的本质保持不变

编辑:更新了常规日志和查询日志,并附有详细示例。


您标记为5.5,但提到5.6;哪有 是否涉及复制?
里克·詹姆斯

@RickJames对不起,它是5.6.19。我已经通过查询和bin日志中的示例更新了问题。同样也没有涉及复制,我只是在注意到调试问题后才打开bin日志。谢谢
艾哈迈德永世Axan

谢谢,有帮助。我看不到BEGINSTART TRANSACTION。您是在使用autocommit=0吗?(我更喜欢begin ... commit;它使交易的范围变得清楚。)
Rick James

因此,框架(弹簧)管理事务,通常会设置autocommit = 0并在最后提交。我猜我们在这里看不到autocommit = 0,因为连接已经处于该状态。
Ahmed Aeon Axan

Answers:


3

我尝试对第二个问题做出假设:

给定提交发生在select之前(commit在14:16:06且select在14:16:07),那么select如何不返回事务插入的行呢?

事务由Spring管理。因此,有可能在运行之前,selectspring引发了一个,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)

我创建一个新会话session2,其中autocommit将其设置为0。在此新会话中,运行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;

现在再次移至会话2:

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

Session2无法看到刚插入的行。如果commit在session2中引发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是否用于其他查询。让我们知道。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.