数据库
首页 > 数据库> > MySQL没有看到选择查询的Commited数据

MySQL没有看到选择查询的Commited数据

作者:互联网

上下文:使用的框架是Spring,所有查询都使用JdbcTemplate运行. Mysql Server版本是5.6.19.该表是一个InnoDB表,默认类似于自动提交和隔离级别可重复读取设置.

问题:在事务中发生插入,并且读取插入的相同数据的选择不会看到数据. select在插入之后和insert事务提交之后运行.

我已启用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'

奇怪的是,第一次插入(249935389)根本不应该是交易的一部分.它是一个单独的API调用,完全不相关.可能是春天将它与交易混合在一起,或者我正在读取日志错误? AFAIK,因为它在同一个线程上,它暗示插入是在事务中.

接下来的两个插入是事务的一部分,看起来像提交. (249936514).现在,选择查询(一般日志中的最后一个)在提交后运行,但它看不到数据.它返回0行.考虑到数据的提交,这怎么可能发生?或者提交不在线程40上?因为它没有线程ID.

总结一下,我有两个问题.

> binlog中的BEGIN是否在INSERT INTO user_geo_loc之前(不是事务的一部分),这是spring / Jdbc或MySql的一个错误,因为它知道这个事务已经提交了(因为事务被写入binlog,当他们成功时,因此永远不会被回滚.
>如果提交发生在select之前(提交是在14:16:06并且select是在14:16:07),那么select如何不返回事务插入的行?

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

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

编辑:使用详细示例更新了常规日志和查询日志.

解决方法:

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

Given the commit happens before the select (commit is at 14:16:06 and
select is at 14:16:07) how is it that the select does not return the
row inserted by the transaction?

交易由Spring管理.因此,在运行select spring之前可能会引发一个启动事务,或者它已经使用了连接来运行另一个查询.

我开始第一个会话,我在表格中模拟插入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;

现在再次移动到session2:

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

Session2无法看到刚刚插入的行.如果在session2中引发了提交,我们可以看到在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用于其他查询,您可以检查常规日志.我们知道了.

标签:mysql-5-6,java,mysql,transaction
来源: https://codeday.me/bug/20190805/1588314.html