#At file:///C:/bzr/mysql-6.0-falcon-team/
2767 Vladislav Vaintroub 2008-08-04
Bug#22165 (crash if update is running in parallel with ALTER)
Bug#35991 (crash if update is running in parallel with TRUNCATE)
Problem : Falcon optimistically allows DDL statements to run
together with read/update. This leads to race conditions, in
particular with TRUNCATE (section pages freed by one threads
accessed by another thread) and ALTER(table is deleted in
between but still accessed by some thread).
There used to be an attempt to synchronize TRUNCATE operation
within Falcon ,via setTruncateLock/clearTruncateLock that is not
working , because TRUNCATE thread disregards/clears locks
set by another threads.
Solution:
synchronize DDL statements using MySQL locks, i.e do not overwrite
lock value given in store_lock in case of TRUNCATE, DROP or ALTER.
Before DDL operation runs, there is still a check whether table has
uncommited records. Operation is denied with ER_CANT_LOCK if there
are some uncommited records.
Falcon truncate synchronization is now removed.
renamed:
mysql-test/suite/falcon_team/r/falcon_bug_22165.result => mysql-test/suite/falcon/r/falcon_bug_22165.result
mysql-test/suite/falcon_team/r/falcon_bug_22173.result => mysql-test/suite/falcon/r/falcon_bug_22173.result
mysql-test/suite/falcon_team/r/falcon_bug_22173a.result => mysql-test/suite/falcon/r/falcon_bug_22173a.result
mysql-test/suite/falcon_team/t/falcon_bug_22165.test => mysql-test/suite/falcon/t/falcon_bug_22165.test
mysql-test/suite/falcon_team/t/falcon_bug_22173.test => mysql-test/suite/falcon/t/falcon_bug_22173.test
mysql-test/suite/falcon_team/t/falcon_bug_22173a.test => mysql-test/suite/falcon/t/falcon_bug_22173a.test
modified:
mysql-test/suite/falcon/t/falcon_bug_37080.test
storage/falcon/StorageTable.cpp
storage/falcon/StorageTable.h
storage/falcon/StorageTableShare.cpp
storage/falcon/StorageTableShare.h
storage/falcon/ha_falcon.cpp
mysql-test/suite/falcon/r/falcon_bug_22165.result
mysql-test/suite/falcon/r/falcon_bug_22173a.result
mysql-test/suite/falcon/t/falcon_bug_22165.test
mysql-test/suite/falcon/t/falcon_bug_22173a.test
per-file messages:
mysql-test/suite/falcon/r/falcon_bug_22165.result
Cleanup the test case. to run stored procedures in parallel, do not use events, but
an extra connection. This allows for more concurrency (events are called only 1 per
second)
mysql-test/suite/falcon/r/falcon_bug_22173.result
This test has previously deadlocked on truncate and was put into falcon_team suite.
Restore it in falcon suite
mysql-test/suite/falcon/r/falcon_bug_22173a.result
This test previously deadlocked on TRUNCATE and was put into falcon_team suite.
Restore in falcon suite.
mysql-test/suite/falcon/t/falcon_bug_22165.test
Adjust result file
mysql-test/suite/falcon/t/falcon_bug_22173.test
This test previously deadlocked on TRUNCATE and was put into falcon_team suite.
Restore in falcon suite.
mysql-test/suite/falcon/t/falcon_bug_22173a.test
This test previously deadlocked on TRUNCATE and was put into falcon_team suite.
Restore in falcon suite.
mysql-test/suite/falcon/t/falcon_bug_37080.test
ER_CANT_LOCK that can come from truncate on a table
with uncommited records.
storage/falcon/StorageTable.cpp
Remove Falcon truncate lock
storage/falcon/StorageTable.h
remove Falcon truncate lock
storage/falcon/StorageTableShare.cpp
remove Falcon truncate lock
storage/falcon/StorageTableShare.h
remove Falcon truncate lock
storage/falcon/ha_falcon.cpp
- remove Falcon truncate lock.
- synchronize DDL statements in external_lock
- in store_lock ,return error if DLL operation (TRUNCATE,DROP,ALTER)
is requested and table has uncommited records.
=== renamed file 'mysql-test/suite/falcon_team/r/falcon_bug_22165.result' => 'mysql-test/suite/falcon/r/falcon_bug_22165.result'
--- a/mysql-test/suite/falcon_team/r/falcon_bug_22165.result 2008-08-04 09:21:20 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_22165.result 2008-08-04 15:53:52 +0000
@@ -1,11 +1,8 @@
*** Bug #22165 ***
SET @@storage_engine = 'Falcon';
-DROP PROCEDURE IF EXISTS db1.p1;
-DROP EVENT IF EXISTS db1.e1;
-DROP EVENT IF EXISTS db1.e2;
-DROP DATABASE IF EXISTS db1;
-CREATE DATABASE db1;
-USE db1;
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
+CREATE TABLE t1 (a bigint, b varchar(1000), c timestamp);
CREATE PROCEDURE p1 ()
begin
declare v int default 0;
@@ -23,13 +20,5 @@ COMMIT;
SET v = v + 1;
end while;
end//
-CREATE TABLE t1 (a bigint, b varchar(1000), c timestamp);
-CREATE EVENT e1 ON SCHEDULE EVERY 1 second DO CALL db1.p1();
-CREATE EVENT e2 ON SCHEDULE EVERY 1 second DO CALL db1.p1();
-SET GLOBAL event_scheduler = 1;
-SET GLOBAL event_scheduler = 0;
-USE test;
-DROP EVENT db1.e1;
-DROP EVENT db1.e2;
-DROP PROCEDURE db1.p1;
-DROP DATABASE db1;
+DROP PROCEDURE p1;
+DROP TABLE t1;
=== renamed file 'mysql-test/suite/falcon_team/r/falcon_bug_22173.result' => 'mysql-test/suite/falcon/r/falcon_bug_22173.result'
=== renamed file 'mysql-test/suite/falcon_team/r/falcon_bug_22173a.result' => 'mysql-test/suite/falcon/r/falcon_bug_22173a.result'
--- a/mysql-test/suite/falcon_team/r/falcon_bug_22173a.result 2008-04-20 08:30:43 +0000
+++ b/mysql-test/suite/falcon/r/falcon_bug_22173a.result 2008-08-04 15:53:52 +0000
@@ -12,6 +12,7 @@ begin declare v1 int default 0;
declare v2 int;
declare continue handler for 1020 begin end;
declare continue handler for 1213 begin end;
+declare continue handler for 1015 begin end;
while v1 < 2500 do
/* SELECT 'insert', v1; */
INSERT INTO t1 VALUES (v1);
=== renamed file 'mysql-test/suite/falcon_team/t/falcon_bug_22165.test' => 'mysql-test/suite/falcon/t/falcon_bug_22165.test'
--- a/mysql-test/suite/falcon_team/t/falcon_bug_22165.test 2008-07-22 13:19:24 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_22165.test 2008-08-04 15:53:52 +0000
@@ -11,14 +11,11 @@ let $engine = 'Falcon';
eval SET @@storage_engine = $engine;
--disable_warnings
-DROP PROCEDURE IF EXISTS db1.p1;
-DROP EVENT IF EXISTS db1.e1;
-DROP EVENT IF EXISTS db1.e2;
-DROP DATABASE IF EXISTS db1;
+DROP TABLE IF EXISTS t1;
+DROP PROCEDURE IF EXISTS p1;
--enable_warnings
+CREATE TABLE t1 (a bigint, b varchar(1000), c timestamp);
-CREATE DATABASE db1;
-USE db1;
delimiter //;
CREATE PROCEDURE p1 ()
begin
@@ -39,18 +36,31 @@ begin
end//
delimiter ;//
-CREATE TABLE t1 (a bigint, b varchar(1000), c timestamp);
+connect (conn1,localhost,root,,);
+connect (conn2,localhost,root,,);
+
-CREATE EVENT e1 ON SCHEDULE EVERY 1 second DO CALL db1.p1();
-CREATE EVENT e2 ON SCHEDULE EVERY 1 second DO CALL db1.p1();
# ----------------------------------------------------- #
# --- Test --- #
# ----------------------------------------------------- #
-SET GLOBAL event_scheduler = 1;
---sleep 60
-SET GLOBAL event_scheduler = 0;
-
+--disable_query_log
+let $i=150;
+while ($i)
+{
+ connection conn1;
+ --send call p1();
+ connection conn2;
+ --send call p1();
+
+ connection conn1;
+ --reap
+ connection conn2;
+ --reap
+
+ dec $i;
+}
+--enable_query_log
# ----------------------------------------------------- #
# --- Check --- #
# ----------------------------------------------------- #
@@ -60,8 +70,9 @@ SET GLOBAL event_scheduler = 0;
# ----------------------------------------------------- #
# --- Final cleanup --- #
# ----------------------------------------------------- #
-USE test;
-DROP EVENT db1.e1;
-DROP EVENT db1.e2;
-DROP PROCEDURE db1.p1;
-DROP DATABASE db1;
+connection default;
+disconnect conn1;
+disconnect conn2;
+DROP PROCEDURE p1;
+DROP TABLE t1;
+
=== renamed file 'mysql-test/suite/falcon_team/t/falcon_bug_22173.test' => 'mysql-test/suite/falcon/t/falcon_bug_22173.test'
=== renamed file 'mysql-test/suite/falcon_team/t/falcon_bug_22173a.test' => 'mysql-test/suite/falcon/t/falcon_bug_22173a.test'
--- a/mysql-test/suite/falcon_team/t/falcon_bug_22173a.test 2008-04-20 08:30:43 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_22173a.test 2008-08-04 15:53:52 +0000
@@ -31,6 +31,7 @@ begin declare v1 int default 0;
declare v2 int;
declare continue handler for 1020 begin end;
declare continue handler for 1213 begin end;
+declare continue handler for 1015 begin end;
while v1 < 2500 do
/* SELECT 'insert', v1; */
INSERT INTO t1 VALUES (v1);
@@ -52,7 +53,6 @@ delimiter ;//
--echo # Switch to connection conn1
connection conn1;
---real_sleep 1
call p1();
--echo # Switch to connection default
=== modified file 'mysql-test/suite/falcon/t/falcon_bug_37080.test'
--- a/mysql-test/suite/falcon/t/falcon_bug_37080.test 2008-07-16 17:52:19 +0000
+++ b/mysql-test/suite/falcon/t/falcon_bug_37080.test 2008-08-04 15:53:52 +0000
@@ -31,8 +31,10 @@ while ($num)
connection default;
--send truncate table t1;
connection conn1;
+ --error 0,ER_CANT_LOCK
--reap
connection default;
+ --error 0,ER_CANT_LOCK
--reap
dec $num;
}
=== modified file 'storage/falcon/StorageTable.cpp'
--- a/storage/falcon/StorageTable.cpp 2008-05-02 22:09:28 +0000
+++ b/storage/falcon/StorageTable.cpp 2008-08-04 15:53:52 +0000
@@ -56,8 +56,6 @@ StorageTable::StorageTable(StorageConnec
StorageTable::~StorageTable(void)
{
- clearTruncateLock();
-
if (bitmap)
((Bitmap*) bitmap)->release();
@@ -85,7 +83,6 @@ int StorageTable::open(void)
int StorageTable::deleteTable(void)
{
- clearTruncateLock();
int ret = share->deleteTable(storageConnection);
if (ret == 0)
@@ -96,32 +93,12 @@ int StorageTable::deleteTable(void)
int StorageTable::truncateTable(void)
{
- clearTruncateLock();
- Sync sync(share->syncTruncate, "StorageTable::truncateTable");
- sync.lock(Exclusive);
clearRecord();
int ret = share->truncateTable(storageConnection);
-
return ret;
}
-void StorageTable::clearTruncateLock(void)
-{
- if (haveTruncateLock)
- {
- share->clearTruncateLock();
- haveTruncateLock = false;
- }
-}
-void StorageTable::setTruncateLock()
-{
- if (!haveTruncateLock)
- {
- share->setTruncateLock();
- haveTruncateLock = true;
- }
-}
int StorageTable::insert(void)
{
=== modified file 'storage/falcon/StorageTable.h'
--- a/storage/falcon/StorageTable.h 2008-05-02 22:09:28 +0000
+++ b/storage/falcon/StorageTable.h 2008-08-04 15:53:52 +0000
@@ -64,8 +64,7 @@ public:
void clearAlter(void);
bool setAlter(void);
- void clearTruncateLock(void);
- void setTruncateLock();
+
virtual void setConnection(StorageConnection* connection);
virtual void clearIndexBounds(void);
=== modified file 'storage/falcon/StorageTableShare.cpp'
--- a/storage/falcon/StorageTableShare.cpp 2008-07-15 18:57:27 +0000
+++ b/storage/falcon/StorageTableShare.cpp 2008-08-04 15:53:52 +0000
@@ -70,10 +70,7 @@ StorageTableShare::StorageTableShare(Sto
sequence = NULL;
tempTable = tempTbl;
setPath(path);
- syncTruncate = new SyncObject;
- syncTruncate->setName("StorageTableShare::syncTruncate");
- truncateLockCount = 0;
-
+
if (tempTable)
tableSpace = TEMPORARY_TABLESPACE;
else if (tableSpaceName && tableSpaceName[0])
@@ -84,11 +81,7 @@ StorageTableShare::StorageTableShare(Sto
StorageTableShare::~StorageTableShare(void)
{
- while (truncateLockCount > 0)
- clearTruncateLock();
-
delete syncObject;
- delete syncTruncate;
delete [] impure;
if (storageDatabase)
@@ -605,21 +598,6 @@ JString StorageTableShare::lookupPathNam
return path;
}
-void StorageTableShare::setTruncateLock(void)
-{
- INTERLOCKED_INCREMENT(truncateLockCount);
- syncTruncate->lock(NULL, Shared);
-}
-
-void StorageTableShare::clearTruncateLock(void)
-{
- if (truncateLockCount > 0)
- {
- INTERLOCKED_DECREMENT(truncateLockCount);
- syncTruncate->unlock();
-// syncTruncate->unlock(NULL, Shared);
- }
-}
int StorageTableShare::getFieldId(const char* fieldName)
{
=== modified file 'storage/falcon/StorageTableShare.h'
--- a/storage/falcon/StorageTableShare.h 2008-07-09 04:38:02 +0000
+++ b/storage/falcon/StorageTableShare.h 2008-08-04 15:53:52 +0000
@@ -126,8 +126,6 @@ public:
uint64 estimateCardinality(void);
bool tableExists(void);
JString lookupPathName(void);
- void setTruncateLock(void);
- void clearTruncateLock(void);
static const char* getDefaultRoot(void);
static const char* cleanupTableName(const char* name, char* buffer, int bufferLength, char *schema, int schemaLength);
@@ -142,7 +140,6 @@ public:
unsigned char *impure;
int initialized;
SyncObject *syncObject;
- SyncObject *syncTruncate;
StorageDatabase *storageDatabase;
StorageHandler *storageHandler;
Table *table;
@@ -150,7 +147,6 @@ public:
Sequence *sequence;
Format *format; // format for insertion
int numberIndexes;
- volatile INTERLOCK_TYPE truncateLockCount;
bool tempTable;
int getFieldId(const char* fieldName);
};
=== modified file 'storage/falcon/ha_falcon.cpp'
--- a/storage/falcon/ha_falcon.cpp 2008-07-29 10:45:39 +0000
+++ b/storage/falcon/ha_falcon.cpp 2008-08-04 15:53:52 +0000
@@ -420,9 +420,6 @@ StorageInterface::StorageInterface(handl
StorageInterface::~StorageInterface(void)
{
- if (storageTable)
- storageTable->clearTruncateLock();
-
if (activeBlobs)
freeActiveBlobs();
@@ -534,10 +531,6 @@ StorageConnection* StorageInterface::get
int StorageInterface::close(void)
{
DBUG_ENTER("StorageInterface::close");
-
- if (storageTable)
- storageTable->clearTruncateLock();
-
unmapFields();
// Temporarily comment out DTrace probes in Falcon, see bug #36403
@@ -917,7 +910,9 @@ THR_LOCK_DATA **StorageInterface::store_
if ( (lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE)
&& !(thd_in_lock_tables(thd) && sql_command == SQLCOM_LOCK_TABLES)
&& !(thd_tablespace_op(thd))
- // && (sql_command != SQLCOM_TRUNCATE)
+ && (sql_command != SQLCOM_ALTER_TABLE)
+ && (sql_command != SQLCOM_DROP_TABLE)
+ && (sql_command != SQLCOM_TRUNCATE)
&& (sql_command != SQLCOM_OPTIMIZE)
&& (sql_command != SQLCOM_CREATE_TABLE)
)
@@ -1020,7 +1015,7 @@ int StorageInterface::delete_all_rows()
if (!storageTable)
storageTable = storageConnection->getStorageTable(storageShare);
- storageTable->truncateTable();
+ ret = storageTable->truncateTable();
DBUG_RETURN(ret);
}
@@ -1262,10 +1257,6 @@ void StorageInterface::startTransaction(
if (!storageConnection->transactionActive)
{
storageConnection->startTransaction(isolation);
-
- if (storageTable)
- storageTable->setTruncateLock();
-
trans_register_ha(mySqlThread, true, falcon_hton);
}
@@ -1873,12 +1864,7 @@ int StorageInterface::external_lock(THD
storageConnection->setCurrentStatement(NULL);
if (!thd_test_options(thd, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
- {
- if (storageTable)
- storageTable->clearTruncateLock();
-
storageConnection->endImplicitTransaction();
- }
else
storageConnection->releaseVerb();
@@ -1891,10 +1877,11 @@ int StorageInterface::external_lock(THD
storageConnection->setCurrentStatement(thd->query);
insertCount = 0;
- bool isTruncate = false;
-
+
switch (thd_sql_command(thd))
{
+ case SQLCOM_TRUNCATE:
+ case SQLCOM_DROP_TABLE:
case SQLCOM_ALTER_TABLE:
case SQLCOM_DROP_INDEX:
case SQLCOM_CREATE_INDEX:
@@ -1903,18 +1890,10 @@ int StorageInterface::external_lock(THD
if (ret)
{
- if (storageTable)
- storageTable->clearTruncateLock();
-
DBUG_RETURN(error(ret));
}
}
break;
-
- case SQLCOM_TRUNCATE:
- isTruncate = true;
- break;
-
default:
break;
}
@@ -1927,9 +1906,6 @@ int StorageInterface::external_lock(THD
if (storageConnection->startTransaction(isolation))
{
- if (!isTruncate && storageTable)
- storageTable->setTruncateLock();
-
trans_register_ha(thd, true, falcon_hton);
}
@@ -1942,9 +1918,6 @@ int StorageInterface::external_lock(THD
if (storageConnection->startImplicitTransaction(isolation))
{
- if (!isTruncate && storageTable)
- storageTable->setTruncateLock();
-
trans_register_ha(thd, false, falcon_hton);
}
}
Thread |
---|
• bzr commit into mysql-6.0-falcon branch (vvaintroub:2767) Bug#22165 Bug#35991 | Vladislav Vaintroub | 4 Aug |