summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/bdb-crash.result7
-rw-r--r--mysql-test/t/bdb-crash.test12
-rw-r--r--sql/ha_berkeley.cc38
-rw-r--r--sql/handler.h1
-rw-r--r--sql/sql_table.cc6
5 files changed, 64 insertions, 0 deletions
diff --git a/mysql-test/r/bdb-crash.result b/mysql-test/r/bdb-crash.result
index 5079368ea21..16e51c61504 100644
--- a/mysql-test/r/bdb-crash.result
+++ b/mysql-test/r/bdb-crash.result
@@ -30,3 +30,10 @@ ChargeID ServiceID ChargeDate ChargeAmount FedTaxes ProvTaxes ChargeStatus Charg
1 1 2001-03-01 1.00 1.00 1.00 New blablabla NULL now
2 1 2001-03-01 1.00 1.00 1.00 New NULL NULL now
drop table t1;
+create table t1 (a int) engine=bdb;
+set autocommit=0;
+insert into t1 values(1);
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status Operation need committed state
+drop table t1;
diff --git a/mysql-test/t/bdb-crash.test b/mysql-test/t/bdb-crash.test
index 4575a612728..a966ea4659d 100644
--- a/mysql-test/t/bdb-crash.test
+++ b/mysql-test/t/bdb-crash.test
@@ -34,3 +34,15 @@ INSERT INTO t1
VALUES(NULL,1,'2001-03-01',1,1,1,'New',NULL,NULL,'now');
select * from t1;
drop table t1;
+
+#
+# Test for bug #2342 "Running ANALYZE TABLE on bdb table
+# inside a transaction hangs server thread"
+#
+
+create table t1 (a int) engine=bdb;
+
+set autocommit=0;
+insert into t1 values(1);
+analyze table t1;
+drop table t1; \ No newline at end of file
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index 35e731f20da..d0ce8f1fdb2 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -2099,6 +2099,44 @@ int ha_berkeley::analyze(THD* thd, HA_CHECK_OPT* check_opt)
{
DB_BTREE_STAT *stat=0;
uint i;
+ DB_TXN_STAT *txn_stat_ptr= 0;
+
+ /*
+ If it's a merge conflict here (4.0->4.1), please ignore it!
+
+ The reason of the conflict is the difference between versions of bdb:
+ mysql-4.0 uses bdb 3.2.9
+ mysql-4.1 uses bdb 4.1.24
+ Older one has global functions txn_stat and txn_id but
+ newer one has DB_ENV->txn_stat and DB_TXN->id
+ */
+ if (!txn_stat(db_env, &txn_stat_ptr, 0) &&
+ txn_stat_ptr && txn_stat_ptr->st_nactive>=2)
+ {
+ DB_TXN_ACTIVE *atxn_stmt= 0, *atxn_all= 0;
+
+ DB_TXN *txn_all= (DB_TXN*) thd->transaction.all.bdb_tid;
+ u_int32_t all_id= txn_id(txn_all);
+
+ DB_TXN *txn_stmt= (DB_TXN*) thd->transaction.stmt.bdb_tid;
+ u_int32_t stmt_id= txn_id(txn_stmt);
+
+ DB_TXN_ACTIVE *cur= txn_stat_ptr->st_txnarray;
+ DB_TXN_ACTIVE *end= cur + txn_stat_ptr->st_nactive;
+ for (; cur!=end && (!atxn_stmt || !atxn_all); cur++)
+ {
+ if (cur->txnid==all_id) atxn_all= cur;
+ if (cur->txnid==stmt_id) atxn_stmt= cur;
+ }
+
+ if (atxn_stmt && atxn_all &&
+ log_compare(&atxn_stmt->lsn,&atxn_all->lsn))
+ {
+ free(txn_stat_ptr);
+ return HA_ADMIN_REJECT;
+ }
+ free(txn_stat_ptr);
+ }
for (i=0 ; i < table->keys ; i++)
{
diff --git a/sql/handler.h b/sql/handler.h
index ead0ed106c7..ac00050b777 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -40,6 +40,7 @@
#define HA_ADMIN_CORRUPT -3
#define HA_ADMIN_INTERNAL_ERROR -4
#define HA_ADMIN_INVALID -5
+#define HA_ADMIN_REJECT -6
/* Bits in table_flags() to show what database can do */
#define HA_READ_RND_SAME 1 /* Read RND-record to KEY-record
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 48151ef55b9..7507ab16968 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -1330,6 +1330,12 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
net_store_data(packet, "Operation failed");
break;
+ case HA_ADMIN_REJECT:
+ net_store_data(packet,"status");
+ net_store_data(packet,"Operation need committed state");
+ open_for_modify= false;
+ break;
+
case HA_ADMIN_ALREADY_DONE:
net_store_data(packet, "status");
net_store_data(packet, "Table is already up to date");