1、設置非自動提交 set autocommit=0;? 這時候 for update才會起作用
2、一般用法 set autocommit=0;? for update(加鎖)? ;? commit/rollback; set autocommit=1;
首先看一下,set autocommit=0 后,執行哪些語句會自動加鎖,加的是什么鎖?
測試環境:5.6.16?? innnoDB引擎 非自動提交方式(即 set autocommit=0;)
測試過程:執行 select * from w_help ;這個語句,并不會加鎖 其他命令窗口一樣可以增刪改查;測試代碼如下
DELIMITER $$DROP PROCEDURE IF EXISTS`test_release`.`test_Lock`$$CREATE DEFINER=`encysys48`@`%` PROCEDURE `test_Lock`(IN v_id VARCHAR(20),IN v_flag VARCHAR(10))BEGIN
set autocommit=0;select t.flag from test_lock t where t.hf_serial = v_id for update;/*update test_lock t
set t.flag = v_flag
where t.hf_serial = v_id;*/
--insert into w_help(char_content) values ('aaaaaaaaaaaaaaaaaaaa') for update;
--delete from w_help where w_help.id = '451';
select * fromw_help ;selectsleep(v_flag);commit;set autocommit=1;END$$
DELIMITER ;
存儲過程 加鎖后SLEEP
call test_Lock(1,10) --調用存儲過程
在釋放鎖之前,下面的語句都是可以執行的,說明表并沒有加鎖
select * fromw_help;insert w_help(char_content) values("abcd");updatew_help tset t.char_content = '12345'
where t.id = "458";delete from w_help --where w_help.id = '458'
執行 insert into w_help(char_content) values ('aaaaaaaaaaaaaaaaaaaa') ;這個語句,只會給一行加鎖,(值得一提的是 這個語句后面不能跟 for update 否則會報錯,不知道是我寫的語法問題,還是根本就不能加) insert into w_help(char_content) values ('aaaaaaaaaaaaaaaaaaaa') for update; 就會報錯;
其他事務語句執行情況如下:
select * from w_help; --可以執行
insert w_help(char_content) values("abcd"); --可以執行
updatew_help tset t.char_content = '12345'
where t.id = "464"; --可以執行
delete from w_help where w_help.id = '464'; --可以執行
delete from w_help --不能執行會等待鎖釋放后執行
執行 update w_help t
set t.char_content = v_flag
where t.id ="476"; 這個語句,只會給一行加鎖,(前提是指明了主鍵)
其他事務語句執行情況如下:
select * from w_help; --可以執行
insert w_help(char_content) values("abcd"); --可以執行
updatew_help tset t.char_content = '12345'
where t.id = "479"; --可以執行
delete from w_help where w_help.id = '478'; --可以執行
delete from w_help --不能執行
如果不指明主鍵 則會鎖住整個表,其他事務語句執行情況如下:
select * from w_help; --可以執行
insert w_help(char_content) values("abcd"); --可以執行并且不會被update
updatew_help tset t.char_content = '12345'
where t.id = "489"; --不能執行 等待鎖被釋放后繼續執行
delete from w_help where w_help.id = '489'; --不能執行 等待鎖被釋放后繼續執行
delete from w_help --不能執行 等待鎖被釋放后繼續執行
執行 delete from w_help where w_help.id = '490';這個語句 產生行級鎖,
其他事務語句執行情況如下:
select * from w_help; --可以執行
insert w_help(char_content) values("abcd"); --可以執行
updatew_help tset t.char_content = '12345'
where t.id = "490"; --被鎖定的唯一一行 不能執行
delete from w_help where w_help.id = '488'; --不是被鎖定的那一行,可以執行
delete from w_help --不能執行
還有一個奇葩的問題 select * from w_help for update; 并不能限制其他線程讀取數據;可以限制其他線程加鎖(即其他線程便不能加鎖了)
這樣的的話怎么防止讀臟數據就是個問題了;不過我是在兩個連接中測試的,即一個連接執行此語句,另一個連接仍然可以讀數據,但是不可以修改!
所以,如果修改數據,select 時一定要 for update,否則就會有致命錯誤!
最后附上測試用的亂七八糟的代碼,不值得看,只是做個備份而已,說不定哪時會用到;
DELIMITER $$DROP PROCEDURE IF EXISTS`test_release`.`test_Lock`$$CREATE DEFINER=`encysys48`@`%` PROCEDURE `test_Lock`(IN v_id VARCHAR(20),IN v_flag VARCHAR(10))BEGIN
set autocommit=0;select t.flag from test_lock t where t.hf_serial = v_id for update;/*update w_help t
set t.char_content = v_flag ;
-- where t.id ="476";
-- insert into w_help(char_content) values ('aaaaaaaaaaaaaaaaaaaa') ;*/
delete from w_help where w_help.id = '490';--select * from w_help ;
selectsleep(v_flag);commit;set autocommit=1;END$$
DELIMITER ;--
select * from w_help; --可以執行
insert w_help(char_content) values("abcd"); --可以執行
updatew_help tset t.char_content = '12345'
where t.id = "490"; --被鎖定的唯一一行 不能執行
delete from w_help where w_help.id = '488'; --不是同一行,可以執行
delete from w_help --不能執行
updatew_help tset t.char_content = "666" where t.id = "489";
亂七八糟