锁表为何失败CREATE PROCEDURE `ba`(id int)
beginlock table ba2 read;
update  ba2 a, (select max(a) as aa  from ba2 where a < id) b set a.b=1 where a.a=b.aa;
delete from ba2 where a=id;
unlock tables;
end; 我用工具窗口执行下面的代码
lock table ba2 read;
update  ba2 a, (select max(a) as aa  from ba2 where a < id) b set a.b=1 where a.a=b.aa;
delete from ba2 where a=id;
unlock tables;失败提示:1100--table ba2 was not locked with LOCK tAbles;why 锁表为何失败  

解决方案 »

  1.   

    lock table ba2 WRITE, ba2 a WRITE;
      

  2.   

    感谢楼上 你代码成功通过但是想知道原因:(感叹)
    为什么我的会是失败lock table ba2 read; 
    你的write会成功(使用别名成功)
      

  3.   

    运到新问题
    CREATE PROCEDURE `ba`(id int)
    beginock table ba2 WRITE, ba2 a WRITE;
    update  ba2 a, (select max(a) as aa  from ba2 where a < id) b set a.b=1 where a.a=b.aa;
    delete from ba2 where a=id;
    unlock tables;
    end; 提示错误  ---1314--lock is not allowed in store procedure
     
      

  4.   

    Stored routines cannot contain arbitrary SQL statements. The following statements are disallowed: The locking statements LOCK TABLES and UNLOCK TABLES. 
      

  5.   

    sorry 没看到这个申明
    你的意思只能用事务来实现 ?????
    这里事务该如何作 
    (或者我在java代码里 用程序来写?????)
      

  6.   

    12.4.1. START TRANSACTION, COMMIT, and ROLLBACK Syntax
    START TRANSACTION [WITH CONSISTENT SNAPSHOT] | BEGIN [WORK]
    COMMIT [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
    ROLLBACK [WORK] [AND [NO] CHAIN] [[NO] RELEASE]
    SET autocommit = {0 | 1}The START TRANSACTION or BEGIN statement begins a new transaction. COMMIT commits the current transaction, making its changes permanent. ROLLBACK rolls back the current transaction, canceling its changes. The SET autocommit statement disables or enables the default autocommit mode for the current session. 
      

  7.   

    因为 LOCK 锁阻止其他用户的访问,所以应该尽可能快的执行 UNLOCK 命令。
    MySQL LOCK 类型MySQL LOCK 锁的类型有四种,每一种锁定的范围不同:
    READ所有的用户只能读取被锁表,不能对表进行修改(包括执行 LOCK 的用户),当表不存在 WRITE 写锁时 READ 读锁被执行。
    READ LOCAL除了允许 INSERT 命令以外执行的锁与 READ 相同。
    WRITE除了当前用户被允许读取和修改被锁表外,其他用户的所有访问被完全阻止。一个 WRITE 写锁被执行仅当所有其他锁取消时。
    LOW PRIORITY WRITE低优先级的读锁,在等待时间内(等待其他锁取消),其他用户的访问将被认为是执行了 READ 读锁,因此将增加等待时间。 java 程序时下如下:
    conn =  connection();
    conn.setAutocommit(false);
    lockStatement=conn.createStatement();
    lockStatement.execute("Lock tables mm write");
    ps=conn.prepareStatement("select * from  message where"");
    rs=ps.executeQuery();
    where....rs.next();...
    messDBO.insert....()catch(sqlexception e)
    {
    commit=false;
    throw e;
    }
    finally{
    if(commit)
    conn.commit();
    else
    conn.rollback();stagement unlockStagement=conn.createStagement();
    unlockStagement.execute("unlock Tables");
    if(ps!=null) ps.close();
    if(lockStagement!=null) unlockStagement.close();
    if(unlockStagement!=null) unlockStagement.cluse();
    freeconnection()}
    现在就缺楼上补充
    事务来实现 ?????
    这里事务该如何作
      

  8.   

    LOCK  TABLES        是为当前线程锁定表。 UNLOCK  TABLES  释放被当前线程持有的任何锁。还有以下几条规则:1. 如果一个线程获得在一个表上的一个READ锁,该线程和所有其他线程只能从表中读。   测试确实如此 提示不能埂新  (无论当地线程还是其他线程)2. 如果一个线程获得一个表上的一个WRITE锁,那么只有持锁的线程READ或WRITE表,其他线程被阻止。
    其他是不能读的3. 当线程发出另外一个LOCK  TABLES时,或当服务器的连接被关闭时,
    当前线程锁定的所有表会自动被解锁。---------------这个是很重要的 
    4. 当前进程无法 访问没有被LOCK 的表   这个不清楚的可以在winows 下开两个命令窗口 (就相当是两个进程了) 然后试
      

  9.   

    drop procedure if exists pro_rep_shadow_rs;  
    delimiter |  
    ----------------------------------  
    -- rep_shadow_rs  
    -- 用来处理信息的增加,更新和删除  
    -- 每次只更新上次以来没有做过的数据  
    -- 根据不同的标志位  
    -- 需要一个输出的参数,  
    -- 如果返回为0,则调用失败,事务回滚  
    -- 如果返回为1,调用成功,事务提交  
    --  
    -- 测试方法  
    -- call pro_rep_shadow_rs(@rtn);  
    -- select @rtn;  
    ----------------------------------  
    create procedure pro_rep_shadow_rs(out rtn int)  
    begin  
        -- 声明变量,所有的声明必须在非声明的语句前面  
        declare iLast_rep_sync_id int default -1;  
        declare iMax_rep_sync_id int default -1;  
        -- 如果出现异常,或自动处理并rollback,但不再通知调用方了  
        -- 如果希望应用获得异常,需要将下面这一句,以及启动事务和提交事务的语句全部去掉  
        declare exit handler for sqlexception rollback;  
        -- 查找上一次的  
        select eid into iLast_rep_sync_id from rep_de_proc_log where tbl='rep_shadow_rs';  
        -- 如果不存在,则增加一行  
        if iLast_rep_sync_id=-1 then  
          insert into rep_de_proc_log(rid,eid,tbl) values(0,0,'rep_shadow_rs');  
          set iLast_rep_sync_id = 0;  
        end if;  
          
        -- 下一个数字  
        set iLast_rep_sync_id=iLast_rep_sync_id+1;  
        -- 设置默认的返回值为0:失败  
        set rtn=0;  
          
        -- 启动事务  
        start transaction;  
        -- 查找最大编号  
        select max(rep_sync_id) into iMax_rep_sync_id from rep_shadow_rs;  
        -- 有新数据  
        if iMax_rep_sync_id>=iLast_rep_sync_id then  
            -- 调用  
            call pro_rep_shadow_rs_do(iLast_rep_sync_id,iMax_rep_sync_id);  
            -- 更新日志  
            update rep_de_proc_log set rid=iLast_rep_sync_id,eid=iMax_rep_sync_id where tbl='rep_shadow_rs';  
        end if;  
          
        -- 运行没有异常,提交事务  
        commit;  
        -- 设置返回值为1 
        set rtn=1;  
    end;  
    |  
    delimiter ;  
    drop procedure if exists pro_rep_shadow_rs_do;  
    delimiter |  
    ---------------------------------  
    -- 处理指定编号范围内的数据  
    -- 需要输入2个参数  
    -- last_rep_sync_id 是编号的最小值  
    -- max_rep_sync_id 是编号的最大值  
    -- 无返回值  
    ---------------------------------  
    create procedure pro_rep_shadow_rs_do(last_rep_sync_id int, max_rep_sync_id int)  
    begin  
        declare iRep_operationtype varchar(1);  
        declare iRep_status varchar(1);  
        declare iRep_Sync_id int;  
        declare iId int;  
        -- 这个用于处理游标到达最后一行的情况  
        declare stop int default 0;  
        -- 声明游标  
        declare cur cursor for select id,Rep_operationtype,iRep_status,rep_sync_id from rep_shadow_rs where rep_sync_id between last_rep_sync_id and max_rep_sync_id;  
        -- 声明游标的异常处理,设置一个终止标记  
        declare CONTINUE HANDLER FOR SQLSTATE '02000' SET stop=1;  
          
        -- 打开游标  
        open cur;  
          
        -- 读取一行数据到变量  
        fetch cur into iId,iRep_operationtype,iRep_status,iRep_Sync_id;  
        -- 这个就是判断是否游标已经到达了最后  
        while stop <> 1 do 
            -- 各种判断  
            if iRep_operationtype='I' then  
                insert into rs0811 (id,fnbm) select id,fnbm from rep_shadow_rs where rep_sync_id=iRep_sync_id;  
            elseif iRep_operationtype='U' then  
            begin  
                if iRep_status='A' then  
                    insert into rs0811 (id,fnbm) select id,fnbm from rep_shadow_rs where rep_sync_id=iRep_sync_id;  
                elseif iRep_status='B' then  
                    delete from rs0811 where id=iId;  
                end if;  
            end;  
            elseif iRep_operationtype='D' then  
                delete from rs0811 where id=iId;  
            end if;   
              
            -- 读取下一行的数据   
            fetch cur into iId,iRep_operationtype,iRep_status,iRep_Sync_id;  
        end while;  -- 循环结束  
        close cur; -- 关闭游标  
     end;  
    |