Simultaneous READ COMMITTED transactions updates a select for update columns
You can try to modify the testproc in the following way. I have tryed to be more simple as possible:

DELIMITER $$
CREATE PROCEDURE `testproc`()
BEGIN    
  START TRANSACTION;
  select 'try to acquire lock';
  SELECT CurrentSize, BucketSize into @cursize, @bucketsize 
  FROM TestTable WHERE id = 1 FOR UPDATE;
  select 'acquired lock';  -- only one thread is permitted here
  select sleep(1);  -- some work here
  IF @cursize &lt; @bucketsize THEN
    select concat('CurrentSize &lt; BucketSize (', @cursize, '&lt;', @bucketsize, ')');
    UPDATE TestTable SET CurrentSize = CurrentSize+1 WHERE id = 1;
  ELSE
    select concat('CurrentSize &gt;= BucketSize (', @cursize, '&gt;', @bucketsize, ')');
  END IF;
  COMMIT;  
  select 'lock released';
END $$
DELIMITER ;


The main point is: only one thread can get a lock on the row. Only after the lock is acquired, it can update the counter. (You can use double check design pattern for performance reason but it is a little more complex). You don't need to read uncommited transactions. 

To get an insight, I have called testproc from two or more mysql clients in a loop. So I have defined a loop:

create table TestTable( id int primary key, CurrentSize int, BucketSize int ) engine=innodb;
insert into TestTable (id, CurrentSize, BucketSize) values (1, 1, 5);

delimiter $$
create procedure test_loop()
begin
   declare i int default 30;
   while i &gt;0 do
     call testproc();
     set i = i -1;
   end while;
end $$
delimiter ;


I have launched two mysql clients:

mysql1&gt; call test_loop();

mysql2&gt; call test_loop();

mysql1&gt; select * from TestTable;
+----+-------------+------------+
| id | CurrentSize | BucketSize |
+----+-------------+------------+
|  1 |           5 |          5 |
+----+-------------+------------+
1 row in set (0.00 sec)


You can try to comment out FOR UPDATE into the testproc:

SELECT CurrentSize, BucketSize into @cursize, @bucketsize 
FROM TestTable WHERE id = 1;  -- FOR UPDATE;


If you try several times the previous test, you could get 6 into CurrentSize column.

mysql1&gt; call test_loop();

mysql2&gt; call test_loop();

mysql1&gt; select * from TestTable;
+----+-------------+------------+
| id | CurrentSize | BucketSize |
+----+-------------+------------+
|  1 |           6 |          5 |
+----+-------------+------------+
1 row in set (0.00 sec)


Hope it is help.