|
17 | 17 |
|
18 | 18 | #include "access/nbtree.h"
|
19 | 19 | #include "access/relscan.h"
|
| 20 | +#include "access/xact.h" |
20 | 21 | #include "miscadmin.h"
|
21 | 22 | #include "pgstat.h"
|
22 | 23 | #include "storage/predicate.h"
|
@@ -1258,22 +1259,34 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
|
1258 | 1259 | {
|
1259 | 1260 | /*
|
1260 | 1261 | * We only get here if the index is completely empty. Lock relation
|
1261 |
| - * because nothing finer to lock exists. |
| 1262 | + * because nothing finer to lock exists. Without a buffer lock, it's |
| 1263 | + * possible for another transaction to insert data between |
| 1264 | + * _bt_search() and PredicateLockRelation(). We have to try again |
| 1265 | + * after taking the relation-level predicate lock, to close a narrow |
| 1266 | + * window where we wouldn't scan concurrently inserted tuples, but the |
| 1267 | + * writer wouldn't see our predicate lock. |
1262 | 1268 | */
|
1263 |
| - PredicateLockRelation(rel, scan->xs_snapshot); |
1264 |
| - |
1265 |
| - /* |
1266 |
| - * mark parallel scan as done, so that all the workers can finish |
1267 |
| - * their scan |
1268 |
| - */ |
1269 |
| - _bt_parallel_done(scan); |
1270 |
| - BTScanPosInvalidate(so->currPos); |
| 1269 | + if (IsolationIsSerializable()) |
| 1270 | + { |
| 1271 | + PredicateLockRelation(rel, scan->xs_snapshot); |
| 1272 | + stack = _bt_search(rel, &inskey, &buf, BT_READ, |
| 1273 | + scan->xs_snapshot); |
| 1274 | + _bt_freestack(stack); |
| 1275 | + } |
1271 | 1276 |
|
1272 |
| - return false; |
| 1277 | + if (!BufferIsValid(buf)) |
| 1278 | + { |
| 1279 | + /* |
| 1280 | + * Mark parallel scan as done, so that all the workers can finish |
| 1281 | + * their scan. |
| 1282 | + */ |
| 1283 | + _bt_parallel_done(scan); |
| 1284 | + BTScanPosInvalidate(so->currPos); |
| 1285 | + return false; |
| 1286 | + } |
1273 | 1287 | }
|
1274 |
| - else |
1275 |
| - PredicateLockPage(rel, BufferGetBlockNumber(buf), |
1276 |
| - scan->xs_snapshot); |
| 1288 | + |
| 1289 | + PredicateLockPage(rel, BufferGetBlockNumber(buf), scan->xs_snapshot); |
1277 | 1290 |
|
1278 | 1291 | _bt_initialize_more_data(so, dir);
|
1279 | 1292 |
|
|
0 commit comments