Skip to content

Commit aea615b

Browse files
committed
Hold table locks when needed during analyze
Signed-off-by: Morgan Douglas <[email protected]>
1 parent 3ba5238 commit aea615b

File tree

12 files changed

+138
-18
lines changed

12 files changed

+138
-18
lines changed

bdb/llmeta.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -7489,7 +7489,7 @@ int bdb_get_analyzethreshold_table(tran_type *input_trans, const char *tbl_name,
74897489

74907490
retry:
74917491
/* try to fetch the schema change data */
7492-
rc = bdb_lite_exact_fetch(llmeta_bdb_state, key, &tmpval, sizeof(tmpval),
7492+
rc = bdb_lite_exact_fetch_tran(llmeta_bdb_state, input_trans, key, &tmpval, sizeof(tmpval),
74937493
&fndlen, bdberr);
74947494

74957495
/* tmpval may need to get flipped */

db/db_metrics.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -441,12 +441,12 @@ static int64_t refresh_diskspace(struct dbenv *dbenv, tran_type *tran)
441441
for(ndb = 0; ndb < dbenv->num_dbs; ndb++)
442442
{
443443
db = dbenv->dbs[ndb];
444-
total += calc_table_size_tran(tran, db, 0);
444+
total += calc_table_size(db, 0);
445445
}
446446
for(ndb = 0; ndb < dbenv->num_qdbs; ndb++)
447447
{
448448
db = dbenv->qdbs[ndb];
449-
total += calc_table_size_tran(tran, db, 0);
449+
total += calc_table_size(db, 0);
450450
}
451451
total += bdb_logs_size(dbenv->bdb_env, &num_logs);
452452

db/db_tunables.c

+1
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ extern int gbl_incoherent_logput_window;
186186
extern int gbl_dump_net_queue_on_partial_write;
187187
extern int gbl_dump_full_net_queue;
188188
extern int gbl_debug_partial_write;
189+
extern int gbl_debug_sleep_on_analyze;
189190
extern int gbl_debug_sleep_on_verify;
190191
extern int gbl_max_clientstats_cache;
191192
extern int gbl_decoupled_logputs;

db/db_tunables.h

+4
Original file line numberDiff line numberDiff line change
@@ -2360,6 +2360,10 @@ REGISTER_TUNABLE("test_fdb_io", "Testing fail mode remote sql. (Default: off)",
23602360
TUNABLE_BOOLEAN, &gbl_test_io_errors, INTERNAL, NULL, NULL,
23612361
NULL, NULL);
23622362

2363+
2364+
REGISTER_TUNABLE("debug_sleep_on_analyze", "Sleep for 'n' seconds after releasing views lock in partition analyze (Default: 0)",
2365+
TUNABLE_INTEGER, &gbl_debug_sleep_on_analyze, INTERNAL, NULL, NULL, NULL, NULL);
2366+
23632367
REGISTER_TUNABLE("debug_sleep_in_sql_tick", "Sleep for a second in sql tick. (Default: off)", TUNABLE_BOOLEAN,
23642368
&gbl_debug_sleep_in_sql_tick, INTERNAL | EXPERIMENTAL, NULL, NULL, NULL, NULL);
23652369

db/glue.c

+1-6
Original file line numberDiff line numberDiff line change
@@ -5572,7 +5572,7 @@ void start_exclusive_backend_request(struct dbenv *env)
55725572

55735573
void end_backend_request(struct dbenv *env) { bdb_end_request(env->bdb_env); }
55745574

5575-
uint64_t calc_table_size_tran(tran_type *tran, struct dbtable *db, int skip_blobs)
5575+
uint64_t calc_table_size(struct dbtable *db, int skip_blobs)
55765576
{
55775577
int ii;
55785578
uint64_t size_without_blobs = 0;
@@ -5605,11 +5605,6 @@ uint64_t calc_table_size_tran(tran_type *tran, struct dbtable *db, int skip_blob
56055605
return db->totalsize;
56065606
}
56075607

5608-
uint64_t calc_table_size(struct dbtable *db, int skip_blobs)
5609-
{
5610-
return calc_table_size_tran(NULL, db, skip_blobs);
5611-
}
5612-
56135608
void compr_print_stats()
56145609
{
56155610
int ii;

db/sql.h

+3
Original file line numberDiff line numberDiff line change
@@ -1520,6 +1520,9 @@ void add_fingerprint_to_rawstats(struct rawnodestats *stats,
15201520
*/
15211521
int clnt_check_bdb_lock_desired(struct sqlclntstate *clnt);
15221522

1523+
tran_type *get_read_only_tran();
1524+
int put_read_only_tran(tran_type * const tran);
1525+
15231526
/**
15241527
* Bdb transaction objects with curtran lockid
15251528
*/

db/sqlanalyze.c

+57-9
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@
4646
static int analyze_thread_memory = 1048576;
4747
#endif
4848

49+
int gbl_debug_sleep_on_analyze = 0;
50+
4951
extern void reset_aa_counter(char *tblname);
5052

5153
/* global is-running flag */
@@ -590,11 +592,11 @@ static int local_replicate_write_analyze(char *table)
590592

591593
/* get tbl sampling threshold, if NOT -1 set it
592594
*/
593-
static void get_sampling_threshold(char *table, long long *sampling_thresh)
595+
static void get_sampling_threshold(tran_type *tran, char *table, long long *sampling_thresh)
594596
{
595597
int bdberr = 0;
596598
long long threshold = 0;
597-
bdb_get_analyzethreshold_table(NULL, table, &threshold, &bdberr);
599+
bdb_get_analyzethreshold_table(tran, table, &threshold, &bdberr);
598600

599601
#ifdef DEBUG
600602
printf("retrieving from llmeta saved threshold for table '%s': %lld\n",
@@ -759,20 +761,49 @@ static int analyze_rename_table_for_backup_stats(char *table, struct sqlclntstat
759761

760762
int analyze_regular_table(table_descriptor_t *td, struct sqlclntstate *clnt, char *zErrTab, size_t nErrTab) {
761763
int rc = 0;
764+
int have_schema_lk = 0;
762765
int sampled_table = 0;
763-
struct dbtable *table = get_dbtable_by_name(td->table);
764-
rc = analyze_rename_table_for_backup_stats(td->table, clnt, zErrTab);
766+
tran_type * tran = NULL;
767+
768+
rdlock_schema_lk();
769+
have_schema_lk = 1;
770+
771+
struct dbtable * const table = get_dbtable_by_name(td->table);
772+
if (!table) {
773+
logmsg(LOGMSG_ERROR, "%s: Cannot find table %s\n", __func__, td->table);
774+
rc = 1;
775+
goto err;
776+
}
765777

766-
if (rc)
778+
tran = get_read_only_tran();
779+
if (!tran) {
780+
logmsg(LOGMSG_ERROR, "%s: Could not get tran\n", __func__);
781+
rc = 1;
767782
goto err;
783+
}
768784

769-
/* grab the size of the table */
770-
int64_t totsiz = calc_table_size(table, 1);
785+
rc = bdb_lock_tablename_read(table->handle, table->tablename, tran);
786+
if (rc) {
787+
logmsg(LOGMSG_ERROR, "%s: Failed to acquire read lock on %s\n", __func__,
788+
table->tablename);
789+
rc = 1;
790+
goto err;
791+
}
792+
793+
unlock_schema_lk();
794+
have_schema_lk = 0;
795+
796+
rc = analyze_rename_table_for_backup_stats(td->table, clnt, zErrTab);
797+
if (rc) {
798+
logmsg(LOGMSG_ERROR, "analyze_rename_table_for_backup_stats failed with rc %d\n", rc);
799+
goto err;
800+
}
801+
802+
const int64_t totsiz = calc_table_size(table, 1);
771803

772804
if (sampled_tables_enabled)
773-
get_sampling_threshold(td->table, &sampling_threshold);
805+
get_sampling_threshold(tran, td->table, &sampling_threshold);
774806

775-
/* sample if enabled */
776807
if (sampled_tables_enabled) {
777808
if (totsiz <= sampling_threshold) {
778809
td->scale = 100;
@@ -787,8 +818,19 @@ int analyze_regular_table(table_descriptor_t *td, struct sqlclntstate *clnt, cha
787818
}
788819
}
789820

821+
rc = put_read_only_tran(tran);
822+
tran = NULL;
823+
if (rc) {
824+
logmsg(LOGMSG_ERROR, "%s: Failed to put tran rc(%d)\n", __func__, rc);
825+
goto err;
826+
}
827+
790828
clnt->is_analyze = 1;
791829

830+
if (gbl_debug_sleep_on_analyze) {
831+
sleep(gbl_debug_sleep_on_analyze);
832+
}
833+
792834
/* run analyze as sql query */
793835
char *sql = sqlite3_mprintf("analyzesqlite main.\"%w\"", td->table);
794836
assert(sql != NULL);
@@ -803,6 +845,12 @@ int analyze_regular_table(table_descriptor_t *td, struct sqlclntstate *clnt, cha
803845
if (debug_switch_test_delay_analyze_commit())
804846
sleep(10);
805847
err:
848+
if (have_schema_lk) {
849+
unlock_schema_lk();
850+
}
851+
if (tran) {
852+
put_read_only_tran(tran);
853+
}
806854
if (sampled_table) {
807855
cleanup_sampled_indicies(clnt);
808856
}

db/sqlglue.c

+34
Original file line numberDiff line numberDiff line change
@@ -11790,6 +11790,40 @@ void curtran_puttran(tran_type *tran)
1179011790
bdb_tran_abort(thedb->bdb_env, tran, &bdberr);
1179111791
}
1179211792

11793+
tran_type *get_read_only_tran()
11794+
{
11795+
// Get curtran if we can because it is more efficient.
11796+
// If we can't, then just get a normal transaction.
11797+
11798+
tran_type * tran = curtran_gettran();
11799+
if (tran) { return tran; }
11800+
11801+
int bdberr = 0;
11802+
tran = bdb_tran_begin(thedb->bdb_env, NULL, &bdberr);
11803+
if (!tran) {
11804+
logmsg(LOGMSG_ERROR, "%s: bdb_tran_begin failed bdberr(%d)\n", __func__, bdberr);
11805+
}
11806+
return tran;
11807+
}
11808+
11809+
int put_read_only_tran(tran_type * const tran)
11810+
{
11811+
// Aborts the transaction: Since the transaction is read-only,
11812+
// we don't need to create a commit record.
11813+
11814+
if (tran->is_curtran) {
11815+
curtran_puttran(tran);
11816+
return 0;
11817+
}
11818+
11819+
int bdberr;
11820+
const int rc = bdb_tran_abort(thedb->bdb_env, tran, &bdberr);
11821+
if (rc) {
11822+
logmsg(LOGMSG_ERROR, "%s: bdb_tran_abort failed rc(%d) bdberr(%d)\n", __func__, rc, bdberr);
11823+
}
11824+
return rc;
11825+
}
11826+
1179311827
void clone_temp_table(sqlite3_stmt *stmt, struct temptable *tbl)
1179411828
{
1179511829
int rc;

tests/analyze.test/t17.req

Whitespace-only changes.

tests/analyze.test/t17.req.out

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[analyze t] failed with rc -5 Analyze could not run because of internal problems

tests/analyze.test/t17.req.tool

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
t17.sh

tests/analyze.test/t17.sh

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#!/bin/bash
2+
3+
source ${TESTSROOTDIR}/tools/runit_common.sh
4+
5+
set -e
6+
7+
main() {
8+
# Given
9+
cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "create table t(i int)" > /dev/null
10+
cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "insert into t values(1)" > /dev/null
11+
sendtocluster "exec procedure sys.cmd.send('debug_sleep_on_analyze 5')" > /dev/null
12+
13+
# When
14+
cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "analyze t" &
15+
waitpid=$!
16+
sleep 1
17+
cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "drop table t" > /dev/null
18+
19+
# Then
20+
if ! cdb2sql ${CDB2_OPTIONS} ${DBNAME} default "select 1" > /dev/null;
21+
then
22+
echo "Database not reachable"
23+
return 1
24+
fi
25+
26+
if wait ${waitpid};
27+
then
28+
echo "Expected to fail analyze but passed"
29+
return 1
30+
fi
31+
}
32+
33+
main

0 commit comments

Comments
 (0)