Commit 56cf7a53 authored by knielsen@ymer.(none)'s avatar knielsen@ymer.(none)
Browse files

BUG#27370: Potential inconsistent blob reads for ReadCommitted reads.

The old blob implementation had code that attempted to upgrade the lock mode for
LM_CommittedRead operations, but it did not work properly as it did not recompute
the operation flags.

As a consequence, reading a blob with LM_CommittedRead could return inconsistent
data, with different part of the read data being from different commits done by
other transactions.

The fix is to correctly recompute all necessary flags when upgrading lock mode.
parent 01189d96
Loading
Loading
Loading
Loading
+35 −0
Original line number Diff line number Diff line
set autocommit=1;
reset master;
create table bug16206 (a int);
insert into bug16206 values(1);
start transaction;
insert into bug16206 values(2);
commit;
show binlog events;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
f	n	Format_desc	1	n	Server ver: VERSION, Binlog ver: 4
f	n	Query	1	n	use `test`; create table bug16206 (a int)
f	n	Query	1	n	use `test`; insert into bug16206 values(1)
f	n	Query	1	n	use `test`; insert into bug16206 values(2)
drop table bug16206;
reset master;
create table bug16206 (a int) engine=         bdb;
insert into bug16206 values(0);
insert into bug16206 values(1);
start transaction;
insert into bug16206 values(2);
commit;
insert into bug16206 values(3);
show binlog events;
Log_name	Pos	Event_type	Server_id	End_log_pos	Info
f	n	Format_desc	1	n	Server ver: VERSION, Binlog ver: 4
f	n	Query	1	n	use `test`; create table bug16206 (a int) engine=         bdb
f	n	Query	1	n	use `test`; insert into bug16206 values(0)
f	n	Query	1	n	use `test`; insert into bug16206 values(1)
f	n	Query	1	n	use `test`; BEGIN
f	n	Query	1	n	use `test`; insert into bug16206 values(2)
f	n	Query	1	n	use `test`; COMMIT
f	n	Query	1	n	use `test`; insert into bug16206 values(3)
drop table bug16206;
set autocommit=0;
End of 5.0 tests
+38 −0
Original line number Diff line number Diff line
-- source include/not_embedded.inc
-- source include/have_bdb.inc

#
# Bug #16206: Superfluous COMMIT event in binlog when updating BDB in autocommit mode
#
set autocommit=1;

let $VERSION=`select version()`;

reset master;
create table bug16206 (a int);
insert into bug16206 values(1);
start transaction;
insert into bug16206 values(2);
commit;
--replace_result $VERSION VERSION
--replace_column 1 f 2 n 5 n
show binlog events;
drop table bug16206;

reset master;
create table bug16206 (a int) engine=         bdb;
insert into bug16206 values(0);
insert into bug16206 values(1);
start transaction;
insert into bug16206 values(2);
commit;
insert into bug16206 values(3);
--replace_result $VERSION VERSION
--replace_column 1 f 2 n 5 n
show binlog events;
drop table bug16206;

set autocommit=0;


--echo End of 5.0 tests
+27 −17
Original line number Diff line number Diff line
@@ -113,15 +113,15 @@ private:
 z = Descending (TUX)      - 1  Bit 14
 x = Range Scan (TUX)      - 1  Bit 15
 b = Scan batch            - 10 Bit 16-25 (max 1023)
 d = Distribution key flag
 d = Distribution key flag - 1  Bit 26

           1111111111222222222233
 01234567890123456789012345678901
 ppppppppl hcktzxbbbbbbbbbb
 ppppppppl hcktzxbbbbbbbbbbd
*/

#define PARALLELL_SHIFT     (0)
#define PARALLELL_MASK      (255)
#define PARALLEL_SHIFT     (0)
#define PARALLEL_MASK      (255)

#define LOCK_MODE_SHIFT     (8)
#define LOCK_MODE_MASK      (1)
@@ -148,11 +148,12 @@ private:
#define SCAN_BATCH_MASK  (1023)

#define SCAN_DISTR_KEY_SHIFT (26)
#define SCAN_DISTR_KEY_MASK (1)

inline
Uint8
ScanTabReq::getParallelism(const UintR & requestInfo){
  return (Uint8)((requestInfo >> PARALLELL_SHIFT) & PARALLELL_MASK);
  return (Uint8)((requestInfo >> PARALLEL_SHIFT) & PARALLEL_MASK);
}

inline
@@ -206,58 +207,65 @@ ScanTabReq::clearRequestInfo(UintR & requestInfo){
inline
void 
ScanTabReq::setParallelism(UintR & requestInfo, Uint32 type){
  ASSERT_MAX(type, PARALLELL_MASK, "ScanTabReq::setParallellism");
  requestInfo |= (type << PARALLELL_SHIFT);
  ASSERT_MAX(type, PARALLEL_MASK, "ScanTabReq::setParallelism");
  requestInfo= (requestInfo & ~(PARALLEL_MASK << PARALLEL_SHIFT)) |
               ((type & PARALLEL_MASK) << PARALLEL_SHIFT);
}

inline
void 
ScanTabReq::setLockMode(UintR & requestInfo, Uint32 mode){
  ASSERT_MAX(mode, LOCK_MODE_MASK,  "ScanTabReq::setLockMode");
  requestInfo |= (mode << LOCK_MODE_SHIFT);
  requestInfo= (requestInfo & ~(LOCK_MODE_MASK << LOCK_MODE_SHIFT)) |
               ((mode & LOCK_MODE_MASK) << LOCK_MODE_SHIFT);
}

inline
void 
ScanTabReq::setHoldLockFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setHoldLockFlag");
  requestInfo |= (flag << HOLD_LOCK_SHIFT);
  requestInfo= (requestInfo & ~(HOLD_LOCK_MASK << HOLD_LOCK_SHIFT)) |
               ((flag & HOLD_LOCK_MASK) << HOLD_LOCK_SHIFT);
}

inline
void 
ScanTabReq::setReadCommittedFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setReadCommittedFlag");
  requestInfo |= (flag << READ_COMMITTED_SHIFT);
  requestInfo= (requestInfo & ~(READ_COMMITTED_MASK << READ_COMMITTED_SHIFT)) |
               ((flag & READ_COMMITTED_MASK) << READ_COMMITTED_SHIFT);
}

inline
void 
ScanTabReq::setRangeScanFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setRangeScanFlag");
  requestInfo |= (flag << RANGE_SCAN_SHIFT);
  requestInfo= (requestInfo & ~(RANGE_SCAN_MASK << RANGE_SCAN_SHIFT)) |
               ((flag & RANGE_SCAN_MASK) << RANGE_SCAN_SHIFT);
}

inline
void 
ScanTabReq::setDescendingFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setDescendingFlag");
  requestInfo |= (flag << DESCENDING_SHIFT);
  requestInfo= (requestInfo & ~(DESCENDING_MASK << DESCENDING_SHIFT)) |
               ((flag & DESCENDING_MASK) << DESCENDING_SHIFT);
}

inline
void 
ScanTabReq::setTupScanFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setTupScanFlag");
  requestInfo |= (flag << TUP_SCAN_SHIFT);
  requestInfo= (requestInfo & ~(TUP_SCAN_MASK << TUP_SCAN_SHIFT)) |
               ((flag & TUP_SCAN_MASK) << TUP_SCAN_SHIFT);
}

inline
void
ScanTabReq::setScanBatch(Uint32 & requestInfo, Uint32 flag){
  ASSERT_MAX(flag, SCAN_BATCH_MASK,  "ScanTabReq::setScanBatch");
  requestInfo &= ~(SCAN_BATCH_MASK << SCAN_BATCH_SHIFT);
  requestInfo |= (flag << SCAN_BATCH_SHIFT);
  requestInfo= (requestInfo & ~(SCAN_BATCH_MASK << SCAN_BATCH_SHIFT)) |
               ((flag & SCAN_BATCH_MASK) << SCAN_BATCH_SHIFT);
}

inline
@@ -270,7 +278,8 @@ inline
void 
ScanTabReq::setKeyinfoFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setKeyinfoFlag");
  requestInfo |= (flag << KEYINFO_SHIFT);
  requestInfo= (requestInfo & ~(KEYINFO_MASK << KEYINFO_SHIFT)) |
               ((flag & KEYINFO_MASK) << KEYINFO_SHIFT);
}

inline
@@ -283,7 +292,8 @@ inline
void 
ScanTabReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
  ASSERT_BOOL(flag, "ScanTabReq::setKeyinfoFlag");
  requestInfo |= (flag << SCAN_DISTR_KEY_SHIFT);
  requestInfo= (requestInfo & ~(SCAN_DISTR_KEY_MASK << SCAN_DISTR_KEY_SHIFT)) |
               ((flag & SCAN_DISTR_KEY_MASK) << SCAN_DISTR_KEY_SHIFT);
}

/**
+2 −0
Original line number Diff line number Diff line
@@ -908,6 +908,8 @@ protected:
  // get table or index key from prepared signals
  int getKeyFromTCREQ(Uint32* data, unsigned size);

  virtual void setReadLockMode(LockMode lockMode);

/******************************************************************************
 * These are the private variables that are defined in the operation objects.
 *****************************************************************************/
+1 −0
Original line number Diff line number Diff line
@@ -212,6 +212,7 @@ protected:
  int prepareSend(Uint32  TC_ConnectPtr, Uint64  TransactionId);
  int doSend(int ProcessorId);
  void checkForceSend(bool forceSend);
  virtual void setReadLockMode(LockMode lockMode);

  virtual void setErrorCode(int aErrorCode);
  virtual void setErrorCodeAbort(int aErrorCode);
Loading