Skip to content

Commit 3fc2639

Browse files
zongzhi.czzclaude
andcommitted
Add DuckDB early initialization for crash recovery
- Add InitializeIfNeeded() to trigger DuckDB initialization at startup when duckdb_mode=ON or DuckDB data files exist - Add DataFilesExist() to check for duckdb.db or WAL files - Call InitializeIfNeeded() in mysqld_main() after CreateInstance() to ensure WAL replay happens at startup rather than on first request - Fix merge conflicts in wiki documentation files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2 parents 57c4a2e + 99b28ae commit 3fc2639

File tree

5 files changed

+76
-3
lines changed

5 files changed

+76
-3
lines changed

sql/duckdb/duckdb_manager.cc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ this program; if not, write to the Free Software Foundation, Inc.,
3535
#include "sql/duckdb/duckdb_timezone.h"
3636
#include "sql/mysqld.h"
3737

38+
#include <sys/stat.h>
39+
3840
namespace myduck {
3941

4042
DuckdbManager *DuckdbManager::m_instance = nullptr;
@@ -146,4 +148,53 @@ std::shared_ptr<duckdb::Connection> DuckdbManager::CreateConnection() {
146148
return connection;
147149
}
148150

151+
bool DuckdbManager::DataFilesExist() {
152+
char path[FN_REFLEN];
153+
struct stat st;
154+
155+
// Check for main database file: duckdb.db
156+
fn_format(path, DUCKDB_FILE_NAME, mysql_real_data_home, "", MYF(0));
157+
if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
158+
return true;
159+
}
160+
161+
// Check for WAL file: duckdb.db.wal
162+
fn_format(path, DUCKDB_FILE_NAME, mysql_real_data_home, ".wal", MYF(0));
163+
if (stat(path, &st) == 0 && S_ISREG(st.st_mode)) {
164+
return true;
165+
}
166+
167+
return false;
168+
}
169+
170+
bool DuckdbManager::InitializeIfNeeded() {
171+
if (m_instance == nullptr) {
172+
return true;
173+
}
174+
175+
// Check if we need to initialize DuckDB at startup:
176+
// 1. DuckDB mode is ON, or
177+
// 2. DuckDB data files exist (need crash recovery)
178+
bool need_init = global_mode_on() || DataFilesExist();
179+
180+
if (!need_init) {
181+
return false;
182+
}
183+
184+
if (DataFilesExist()) {
185+
LogErr(INFORMATION_LEVEL, ER_DUCKDB,
186+
"DuckDB data files detected, initializing for crash recovery.");
187+
}
188+
189+
// Trigger initialization (which includes crash recovery via WAL replay)
190+
bool ret = m_instance->Initialize();
191+
if (ret) {
192+
LogErr(ERROR_LEVEL, ER_DUCKDB,
193+
"DuckdbManager::InitializeIfNeeded failed.");
194+
return true;
195+
}
196+
197+
return false;
198+
}
199+
149200
} // namespace myduck

sql/duckdb/duckdb_manager.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,18 @@ class DuckdbManager {
5050

5151
static std::shared_ptr<duckdb::Connection> CreateConnection();
5252

53-
private:
53+
/**
54+
* Initialize DuckDB if needed at startup.
55+
* This should be called after CreateInstance() to trigger crash recovery
56+
* when:
57+
* 1. DuckDB mode is ON (global_mode == DUCKDB_ON), or
58+
* 2. DuckDB data files exist in the data directory
59+
*
60+
* @return true on error, false on success
61+
*/
62+
static bool InitializeIfNeeded();
63+
64+
private:
5465
static DuckdbManager *m_instance;
5566

5667
DuckdbManager();
@@ -59,6 +70,14 @@ class DuckdbManager {
5970

6071
bool Initialize();
6172

73+
/**
74+
* Check if DuckDB data files exist in the data directory.
75+
* Looks for duckdb.db file or WAL files.
76+
*
77+
* @return true if DuckDB data files exist
78+
*/
79+
static bool DataFilesExist();
80+
6281
duckdb::DuckDB *m_database = nullptr;
6382

6483
std::mutex m_mutex;

sql/mysqld.cc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7918,6 +7918,11 @@ int mysqld_main(int argc, char **argv)
79187918

79197919
if (myduck::DuckdbManager::CreateInstance()) unireg_abort(MYSQLD_ABORT_EXIT);
79207920

7921+
// Initialize DuckDB early if needed for crash recovery
7922+
// This ensures WAL replay happens at startup rather than on first request
7923+
if (myduck::DuckdbManager::InitializeIfNeeded())
7924+
unireg_abort(MYSQLD_ABORT_EXIT);
7925+
79217926
if (init_server_components()) unireg_abort(MYSQLD_ABORT_EXIT);
79227927

79237928
if (!server_id_supplied)

wiki/duckdb/how-to-setup-duckdb-node-en.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ mkdir -p \
7373
cat > "$DIR/alisql.cnf" <<EOF2
7474
[mysqld]
7575
# --- Paths ---
76-
basedir =
7776
datadir = ${DIR}/data/dbs
7877
socket = ${DIR}/run/mysql.sock
7978
pid-file = ${DIR}/run/mysqld.pid

wiki/duckdb/how-to-setup-duckdb-node-zh.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ mkdir -p \
8181
cat > "$DIR/alisql.cnf" <<EOF2
8282
[mysqld]
8383
# --- Paths ---
84-
basedir =
8584
datadir = ${DIR}/data/dbs
8685
socket = ${DIR}/run/mysql.sock
8786
pid-file = ${DIR}/run/mysqld.pid

0 commit comments

Comments
 (0)