Commit 174dcb07 authored by gkodinov/kgeorge@magare.gmz's avatar gkodinov/kgeorge@magare.gmz
Browse files

Bug #29644: alter table hangs if records locked in share mode

by long running transaction

On Windows opened files can't be deleted. There was a special
upgraded lock mode (TL_WRITE instead of TL_WRITE_ALLOW_READ) 
in ALTER TABLE to make sure nobody has the table opened
when deleting the old table in ALTER TABLE. This special mode
was causing ALTER TABLE to hang waiting on a lock inside InnoDB.
This special lock is no longer necessary as the server is 
closing the tables it needs to delete in ALTER TABLE.
Fixed by removing the special lock.
Note that this also reverses the fix for bug 17264 that deals with
another consequence of this special lock mode being used.
parent 77ec161c
Loading
Loading
Loading
Loading
+23 −0
Original line number Diff line number Diff line
@@ -735,4 +735,27 @@ COUNT(*)
3072
set @@sort_buffer_size=default;
DROP TABLE t1,t2;
CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB;
INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
INSERT INTO t1 SELECT a + 8  FROM t1;
INSERT INTO t1 SELECT a + 16 FROM t1;
CREATE PROCEDURE p1 ()
BEGIN
DECLARE i INT DEFAULT 50;
DECLARE cnt INT;
START TRANSACTION;
ALTER TABLE t1 ENGINE=InnoDB;
COMMIT;
START TRANSACTION;
WHILE (i > 0) DO
SET i = i - 1;
SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE;
END WHILE;
COMMIT;
END;|
CALL p1();
CALL p1();
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
End of 5.0 tests
+51 −0
Original line number Diff line number Diff line
@@ -741,4 +741,55 @@ set @@sort_buffer_size=default;

DROP TABLE t1,t2;

#
# Bug #29644: alter table hangs if records locked in share mode by long
# running transaction
#

CREATE TABLE t1 (a INT, PRIMARY KEY (a)) ENGINE=InnoDB;

INSERT INTO t1 VALUES (1),(2),(3),(4),(5),(6),(7),(8);
INSERT INTO t1 SELECT a + 8  FROM t1;
INSERT INTO t1 SELECT a + 16 FROM t1;

DELIMITER |;
CREATE PROCEDURE p1 ()
BEGIN
  DECLARE i INT DEFAULT 50;
  DECLARE cnt INT;
  START TRANSACTION;
    ALTER TABLE t1 ENGINE=InnoDB;
  COMMIT;
  START TRANSACTION;
  WHILE (i > 0) DO
    SET i = i - 1;
    SELECT COUNT(*) INTO cnt FROM t1 LOCK IN SHARE MODE;
  END WHILE;
  COMMIT;
END;|

DELIMITER ;|

CONNECT (con1,localhost,root,,);
CONNECT (con2,localhost,root,,);

CONNECTION con1;
SEND CALL p1();
CONNECTION con2;
SEND CALL p1();
CONNECTION default;
CALL p1();

CONNECTION con1;
REAP;
CONNECTION con2;
REAP;
CONNECTION default;
DISCONNECT con1;
DISCONNECT con2;

DROP PROCEDURE p1;
DROP TABLE t1;


--echo End of 5.0 tests
+0 −11
Original line number Diff line number Diff line
@@ -6702,17 +6702,6 @@ ha_innobase::store_lock(
		    && !thd->tablespace_op
		    && thd->lex->sql_command != SQLCOM_TRUNCATE
		    && thd->lex->sql_command != SQLCOM_OPTIMIZE

#ifdef __WIN__
                /* For alter table on win32 for succesful operation
                completion it is used TL_WRITE(=10) lock instead of
                TL_WRITE_ALLOW_READ(=6), however here in innodb handler
                TL_WRITE is lifted to TL_WRITE_ALLOW_WRITE, which causes
                race condition when several clients do alter table
                simultaneously (bug #17264). This fix avoids the problem. */
		    && thd->lex->sql_command != SQLCOM_ALTER_TABLE
#endif

		    && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {

			lock_type = TL_WRITE_ALLOW_WRITE;
+0 −7
Original line number Diff line number Diff line
@@ -2938,13 +2938,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)

  if (table)
  {
#if defined( __WIN__) || defined(OS2)
    /* Win32 can't drop a file that is open */
    if (lock_type == TL_WRITE_ALLOW_READ)
    {
      lock_type= TL_WRITE;
    }
#endif /* __WIN__ || OS2 */
    table_list->lock_type= lock_type;
    table_list->table=	   table;
    table->grant= table_list->grant;