同一条SQL,在同一个TiDB Server实例上执行,前后执行结果不一样

这SQL跑了多久后发现的问题? 发现问之前有什么变更?

线上业务,要在业务低峰期执行了。应用程序日志不认 :rofl:,那TiDB自带的慢日志总没有问题吧,慢日志的sql Digest 是一样的哦

1、这张表是流水表,在23年左右,通过mydumper导出一份全量数据到TiDB,TiDB DM 同步增量。
2、上周五发现这个问题,发现前后没有做过变更操作。整个TiDB集群除了这张表查询有问题,其他表目前业务查询都是正常的

要相信科学,假设让你写一个数据库引擎,能够随机发生问题,估计也是困难吧。 :grinning:

digest 一样有啥问题呢,我看到你日志了,我没有说文本不一样啊🤔,我说的是这种情况啊



MySQL [test]> select * from tt2 order by id asc;
+------+-------------------+
| id   | name              |
+------+-------------------+
|    1 | 0.924106690961967 |
|    2 | B                 |
|    3 | C                 |
+------+-------------------+
3 rows in set (0.00 sec)

MySQL [test]> show variables like '%limit%';
+----------------------------------------+----------------------+
| Variable_name                          | Value                |
+----------------------------------------+----------------------+
| delayed_insert_limit                   | 100                  |
| eq_range_index_dive_limit              | 200                  |
| ft_query_expansion_limit               | 20                   |
| innodb_ft_result_cache_limit           | 2000000000           |
| key_cache_division_limit               | 100                  |
| min_examined_row_limit                 | 0                    |
| open_files_limit                       | 5000                 |
| optimizer_trace_limit                  | 1                    |
| query_cache_limit                      | 1048576              |
| relay_log_space_limit                  | 0                    |
| sql_select_limit                       | 18446744073709551615 |
| tidb_ddl_error_count_limit             | 512                  |
| tidb_enable_plan_cache_for_param_limit | ON                   |
| tidb_enable_rate_limit_action          | OFF                  |
| tidb_opt_limit_push_down_threshold     | 100                  |
| tidb_retry_limit                       | 10                   |
| tidb_schema_version_cache_limit        | 16                   |
| tidb_server_memory_limit               | 80%                  |
| tidb_server_memory_limit_gc_trigger    | 0.7                  |
| tidb_server_memory_limit_sess_min_size | 134217728            |
| tidb_store_limit                       | 0                    |
| tidb_ttl_delete_rate_limit             | 0                    |
| tidb_txn_entry_size_limit              | 0                    |
| updatable_views_with_limit             | YES                  |
+----------------------------------------+----------------------+
24 rows in set (0.00 sec)

MySQL [test]> set session sql_select_limit=2;
Query OK, 0 rows affected (0.00 sec)

MySQL [test]> select * from tt2 order by id asc;
+------+-------------------+
| id   | name              |
+------+-------------------+
|    1 | 0.924106690961967 |
|    2 | B                 |
+------+-------------------+
2 rows in set (0.01 sec)

MySQL [test]> set session sql_select_limit=1;
Query OK, 0 rows affected (0.00 sec)

MySQL [test]> select * from tt2 order by id asc;
+------+-------------------+
| id   | name              |
+------+-------------------+
|    1 | 0.924106690961967 |
+------+-------------------+
1 row in set (5.42 sec)

payment_system.pay_order.id:desc, offset:0, count:501
这个count 501 不可能无缘无故来的。你肯定是用了什么客户端工具,这个客户端为了防止崩溃,自动给你加了limit,mysql workbench就会这样。

sql_select_limit用的默认值

root 15:27: [(none)]> show variables like ‘%limit%’;
±-----------------------------------±---------------------+
| Variable_name | Value |
±-----------------------------------±---------------------+
| delayed_insert_limit | 100 |
| eq_range_index_dive_limit | 200 |
| ft_query_expansion_limit | 20 |
| innodb_ft_result_cache_limit | 2000000000 |
| key_cache_division_limit | 100 |
| min_examined_row_limit | 0 |
| open_files_limit | 5000 |
| optimizer_trace_limit | 1 |
| query_cache_limit | 1048576 |
| relay_log_space_limit | 0 |
| sql_select_limit | 18446744073709551615 |
| tidb_ddl_error_count_limit | 512 |
| tidb_enable_rate_limit_action | ON |
| tidb_opt_limit_push_down_threshold | 100 |
| tidb_retry_limit | 10 |
| tidb_store_limit | 0 |
| updatable_views_with_limit | YES |
±-----------------------------------±---------------------+
17 rows in set (0.01 sec)

这个可以会话级别设置的啊,就是怀疑你的代码有设置这个啊,我以为我前边的回复您都明白啥意思了呢 :joy_cat:

直接拿sql_select_limit这个去代码里面搜一下呗

执行计划出现topN,应该是加了limit 限制,使用的go 代码层面应该有所限制

1、通过workbench、datagrip等客户端工具执行的话,默认会加limit,tidb慢日志也会相应的记录 limit 参数值,但是 count 501 这个慢SQL,在慢日志中并没有 limit 关键字 。
workbench执行的语句:

2、其次,通过应用程序执行的SQL,慢日志里面会带有 arguments 关键字 ; 相反,通过客户端工具执行的SQL,是不会带 arguments 关键字,慢日志里面记录的是原始SQL。
应用程序执行的SQL:

没搜到,相同的应用程序,切换到去查原生的MySQL pay_order表(TiDB 同步的上游),就没有出现结果集不一样的情况了

还在排查中

你错误的 SQL 是不是有 limit 啊。
这是测试:


这是你 error 结果的执行计划:

正确结果的:

我也是觉得问题可能在索引上

的确挺奇怪,期待老师的解答。