Commit bed64d0
committed
[BACKPORT 2024.2][yugabyte#26060] docdb: Fast backward scan returns stale results for select statement with key columns only
Summary:
There are several scenarios where rows are requested by key columns only (including constraints and
aggregates like count). Doc reader have an optimization for this kind of reads: since actual values
does not matter (because key column values can be extracted from the row's doc key) then there is
no need to decode row values and it is enough to check if the row is tombstoned or not.
Unfortunately, this optimization was not updated to take fast backward scan into account:
an iterator stops reading when the firstly met record is not marked with a tombstone value,
which is the case for fast backward scan, which reads a row in the reverse order, from the
oldest to the newest change (per sub doc key), and the oldest record is generally corresponds
to the initially inserted values.
The change updates the algorithm if checking the row existence: the scanning continues until
all row changes have been taken into account to get the actual state of the row.
**Examples of row existence check before the fix**
Example #1
```
Record #1: KEY, T1 => PACKED ROW
Record #2: KEY, COL1, T2 => COL1 NEW VALUE 1
Forward scan / old backward scan:
#1 (alive, T1) => stop
result: row exists.
Fast backward scan:
#2 (alive, T2) => stop
result: row exists.
```
Example #2
```
Record #1: KEY, T3 => DEL
Record #2: KEY, T1 => PACKED ROW
Record #3: KEY, COL1, T2 => COL1 NEW VALUE
Forward scan / old backward scan:
#1 (deleted, T3), #2 (skipped: T1 < T3), #3 (skipped: T2 < T3) => stop
result: row does not exist.
Fast backward scan:
#3 (alive, T2) => stop
result: row exists.
```
Example #3
```
Record #1: KEY, T4 => PACKED ROW
Record #2: KEY, T3 => DEL
Record #3: KEY, T1 => PACKED ROW
Record #4: KEY, COL1, T2 => COL1 NEW VALUE
Forward scan / old backward scan:
#1 (alive, T4) => stop
result: row exists.
Fast backward scan:
#4 (alive, T2) => stop
result: row exists.
```
**Examples of row existence check with the fix**
Example #1
```
Record #1: KEY, T1 => PACKED ROW
Record #2: KEY, COL1, T2 => COL1 NEW VALUE 1
Fast backward scan:
#2 (alive, T2) => #1 (skipped, T1 < T2) => stop
result: row exists.
```
Example #2
```
Record #1: KEY, T3 => DEL
Record #2: KEY, T1 => PACKED ROW
Record #3: KEY, COL1, T2 => COL1 NEW VALUE
Fast backward scan:
#3 (alive, T2) => #2 (skipped: T1 < T2) => #1 (deleted: T3 > T2) => stop
result: row does not exist.
```
Example #3
```
Record #1: KEY, T4 => PACKED ROW
Record #2: KEY, T3 => DEL
Record #3: KEY, T1 => PACKED ROW
Record #4: KEY, COL1, T2 => COL1 NEW VALUE
Fast backward scan:
#4 (alive, T2) => #3 (skipped: T1 < T2) => #2 (deleted: T3 > T2) => #1 (alive: T4 > T3) => stop
result: row exists.
```
Original commit: d8bd1fd / D42212
Jira: DB-15387
Test Plan:
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Fast_WithNulls_kV1
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Fast_WithNulls_kV2
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Fast_WithNulls_kNone
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Fast_WithoutNulls_kV1
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Fast_WithoutNulls_kV2
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Fast_WithoutNulls_kNone
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Slow_WithNulls_kV1
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Slow_WithNulls_kV2
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Slow_WithNulls_kNone
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Slow_WithoutNulls_kV1
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Slow_WithoutNulls_kV2
./yb_build.sh --cxx-test pgwrapper_pg_single_tserver-test --gtest_filter PgSingleTServerTest/PgFastBackwardScanTest.Simple/Slow_WithoutNulls_kNone
**manual testing:**
```
SET yb_use_hash_splitting_by_default = FALSE;
CREATE TABLE t1(c0 int UNIQUE DEFAULT 1);
INSERT INTO t1(c0) VALUES (2);
DELETE FROM t1;
SELECT * FROM t1;
SELECT * FROM t1 GROUP BY t1.c0 ORDER BY t1.c0 DESC;
```
Reviewers: sergei, rthallam
Reviewed By: rthallam
Subscribers: yql, ybase
Tags: #jenkins-ready
Differential Revision: https://phorge.dev.yugabyte.com/D424861 parent 9b62540 commit bed64d0
File tree
2 files changed
+33
-6
lines changed- src/yb
- docdb
- yql/pgwrapper
2 files changed
+33
-6
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
838 | 838 | | |
839 | 839 | | |
840 | 840 | | |
841 | | - | |
| 841 | + | |
| 842 | + | |
| 843 | + | |
| 844 | + | |
842 | 845 | | |
843 | 846 | | |
844 | 847 | | |
| |||
901 | 904 | | |
902 | 905 | | |
903 | 906 | | |
| 907 | + | |
904 | 908 | | |
905 | 909 | | |
906 | 910 | | |
| |||
911 | 915 | | |
912 | 916 | | |
913 | 917 | | |
| 918 | + | |
914 | 919 | | |
915 | 920 | | |
916 | 921 | | |
917 | 922 | | |
918 | 923 | | |
| 924 | + | |
919 | 925 | | |
920 | 926 | | |
921 | 927 | | |
| |||
970 | 976 | | |
971 | 977 | | |
972 | 978 | | |
973 | | - | |
| 979 | + | |
| 980 | + | |
974 | 981 | | |
975 | 982 | | |
976 | 983 | | |
| |||
1046 | 1053 | | |
1047 | 1054 | | |
1048 | 1055 | | |
1049 | | - | |
1050 | | - | |
1051 | | - | |
1052 | 1056 | | |
1053 | 1057 | | |
1054 | 1058 | | |
| |||
1071 | 1075 | | |
1072 | 1076 | | |
1073 | 1077 | | |
1074 | | - | |
| 1078 | + | |
1075 | 1079 | | |
1076 | 1080 | | |
1077 | 1081 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
871 | 871 | | |
872 | 872 | | |
873 | 873 | | |
| 874 | + | |
| 875 | + | |
| 876 | + | |
| 877 | + | |
| 878 | + | |
| 879 | + | |
| 880 | + | |
874 | 881 | | |
875 | 882 | | |
876 | 883 | | |
877 | 884 | | |
| 885 | + | |
| 886 | + | |
| 887 | + | |
| 888 | + | |
| 889 | + | |
| 890 | + | |
| 891 | + | |
| 892 | + | |
| 893 | + | |
878 | 894 | | |
879 | 895 | | |
880 | 896 | | |
| |||
906 | 922 | | |
907 | 923 | | |
908 | 924 | | |
| 925 | + | |
909 | 926 | | |
910 | 927 | | |
911 | 928 | | |
| |||
920 | 937 | | |
921 | 938 | | |
922 | 939 | | |
| 940 | + | |
923 | 941 | | |
924 | 942 | | |
925 | 943 | | |
| |||
928 | 946 | | |
929 | 947 | | |
930 | 948 | | |
| 949 | + | |
931 | 950 | | |
932 | 951 | | |
933 | 952 | | |
934 | 953 | | |
935 | 954 | | |
936 | 955 | | |
937 | 956 | | |
| 957 | + | |
938 | 958 | | |
939 | 959 | | |
940 | 960 | | |
941 | 961 | | |
942 | 962 | | |
| 963 | + | |
943 | 964 | | |
944 | 965 | | |
945 | 966 | | |
946 | 967 | | |
947 | 968 | | |
948 | 969 | | |
949 | 970 | | |
| 971 | + | |
950 | 972 | | |
951 | 973 | | |
952 | 974 | | |
| |||
956 | 978 | | |
957 | 979 | | |
958 | 980 | | |
| 981 | + | |
959 | 982 | | |
960 | 983 | | |
961 | 984 | | |
| |||
0 commit comments