@@ -3556,6 +3556,18 @@ ha_ndbcluster::scan_handle_lock_tuple(NdbScanOperation *scanOp,
3556
3556
DBUG_RETURN(0);
3557
3557
}
3558
3558
3559
+ /*
3560
+ Some MySQL table locks are mapped to Ndb internal exclusive
3561
+ row locks to achieve part of the table locking semantics. If rows are
3562
+ not exclusively locked a new batch of rows need to be fetched.
3563
+ */
3564
+ static bool table_lock_not_mapped_to_row_lock(enum thr_lock_type lock_type)
3565
+ {
3566
+ return
3567
+ (lock_type < TL_READ_NO_INSERT &&
3568
+ lock_type != TL_READ_WITH_SHARED_LOCKS);
3569
+ }
3570
+
3559
3571
inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
3560
3572
{
3561
3573
DBUG_ENTER("fetch_next");
@@ -3567,8 +3579,7 @@ inline int ha_ndbcluster::fetch_next(NdbScanOperation* cursor)
3567
3579
if ((error= scan_handle_lock_tuple(cursor, trans)) != 0)
3568
3580
DBUG_RETURN(error);
3569
3581
3570
- bool contact_ndb= m_lock.type < TL_WRITE_ALLOW_WRITE &&
3571
- m_lock.type != TL_READ_WITH_SHARED_LOCKS;
3582
+ bool contact_ndb= table_lock_not_mapped_to_row_lock(m_lock.type);
3572
3583
do {
3573
3584
DBUG_PRINT("info", ("Call nextResult, contact_ndb: %d", contact_ndb));
3574
3585
/*
@@ -4352,6 +4363,7 @@ int ha_ndbcluster::full_table_scan(const KEY* key_info,
4352
4363
const key_range *end_key,
4353
4364
uchar *buf)
4354
4365
{
4366
+ THD *thd= table->in_use;
4355
4367
int error;
4356
4368
NdbTransaction *trans= m_thd_ndb->trans;
4357
4369
part_id_range part_spec;
@@ -4403,7 +4415,14 @@ int ha_ndbcluster::full_table_scan(const KEY* key_info,
4403
4415
if (unlikely(!(trans= start_transaction(error))))
4404
4416
DBUG_RETURN(error);
4405
4417
4406
- const NdbOperation::LockMode lm = get_ndb_lock_mode(m_lock.type);
4418
+ /*
4419
+ If the scan is part of an ALTER TABLE we need exclusive locks on rows
4420
+ to block parallel updates from other connections to Ndb.
4421
+ */
4422
+ const NdbOperation::LockMode lm =
4423
+ (thd_sql_command(thd) == SQLCOM_ALTER_TABLE) ?
4424
+ NdbOperation::LM_Exclusive
4425
+ : get_ndb_lock_mode(m_lock.type);
4407
4426
NdbScanOperation::ScanOptions options;
4408
4427
options.optionsPresent = (NdbScanOperation::ScanOptions::SO_SCANFLAGS |
4409
4428
NdbScanOperation::ScanOptions::SO_PARALLEL);
@@ -8228,22 +8247,15 @@ THR_LOCK_DATA **ha_ndbcluster::store_lock(THD *thd,
8228
8247
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
8229
8248
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
8230
8249
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
8231
- to t2. Convert the lock to a normal read lock to allow
8250
+ to t2. If table is not explicitly locked or part of an ALTER TABLE
8251
+ then convert the lock to a normal read lock to allow
8232
8252
concurrent inserts to t2. */
8233
8253
8234
- if (lock_type == TL_READ_NO_INSERT && !thd->in_lock_tables)
8254
+ if (lock_type == TL_READ_NO_INSERT &&
8255
+ !thd->in_lock_tables &&
8256
+ sql_command != SQLCOM_ALTER_TABLE)
8235
8257
lock_type= TL_READ;
8236
8258
8237
- /**
8238
- * We need locks on source table when
8239
- * doing offline alter...
8240
- * In 5.1 this worked due to TL_WRITE_ALLOW_READ...
8241
- * but that has been removed in 5.5
8242
- * I simply add this to get it...
8243
- */
8244
- if (sql_command == SQLCOM_ALTER_TABLE)
8245
- lock_type = TL_WRITE;
8246
-
8247
8259
m_lock.type=lock_type;
8248
8260
}
8249
8261
*to++= &m_lock;
0 commit comments