mysql的事务与锁

一、mysql的事务与锁

mysql的锁分行锁与表锁,Lock tables就是表锁,主要应用于非innodb类型的表的事务操作,如果你的表都是innodb,就不需要lock
tables了。当事务与lock tables一起使有时,需要注意以下内容:

(1)Start transaction运行后,如果之前运行了lock tables ….,会自动解锁,同时也会自动提交前面有开始的事务:

Lock tables ….

Start transaction;

Delete …..

Insert into ….

Start transaction;=====这里的start  transaction会自动提交前面的delete和 insert  into…并自动解锁

 (2)commit和rollback只对事务有影响,不会对lock tables产生解锁作用。

(3)lock tables运行后,如果前面运行了start transaction,这里的lock tables就带有commit作用,自动事务提交

(4)lock tables与事务混用时必须这样:

set autocommit = 0;

lock tables 表1 write,表2 read ….;

。。。一些update,delete,insert等;

commit;

unlock tables;

二、innodb的锁表与锁行情形分析

innodb在事务下可以锁定行也可以锁定表,当然对于应用而言,锁定行是最佳性能,当锁定了表,其他进程对表进行write操作时只能队列等候事务的完成再继续。我做了测试,当在事务运行中,如果你的update,delete指定了表的主键或唯一索引,那么事务就只会锁定相应的行,不会锁表,即其他进程还可以对表的其他行进行write操作。

做个测试:

A端——使用mySQL命令行

B端——使用phpMyAdmin

数据表:create table t_role_user(id int not null auto_crement,rid int,uid int,primary key(id));

 在A端运行:

Start transaction;

update t_role_user set rid=99 where id=1;

接着在B端

Update t_role_user set rid=100 where id=2;

B端正常完成,说明此时表没有被锁

接着在B端

Delete from t_role_user  where id=1;

B端的phpMyAdmin页面运行中,进程在等待A端事务完成,因为id=1这行被锁定了

接着在A端commit

然后再看B端发现进程完成了,成功删除id=1表了,这是因为A端的事务完成了,id=1的行解锁了,B端才可以继续

 

OK,我们删除t_role_user表的id字段,只留rid与uid两个字段,再测试:

A端

Start transaction;

update t_role_user set rid=12 where rid=1;

接着在B端

Update t_role_user set rid=100 where rid=2;

B端的phpMyAdmin页面运行中,此时因为update没指定主键,虽然B端更新的行不是A端事务操作的行,但t_role_user整个表还是被锁住了,所以B端必须等A端事务完成了才可以继续。

接着在A端Commit

再回头看B端,发现sql执行完毕了。

 

事务中update,delete指定主键可以帮助innodb锁定行而不需要锁定整个表,我再测试对rid与uid建立联合的唯一索引,如果在事务中update或delete有指定rid=? And uid=?时,innodb也只会锁行不会锁表,说明唯一索引也可以帮助innodb锁行不锁表

相关参考:

http://dev.mysql.com/doc/refman/5.5/en/lock-tables-and-transactions.html


相关评论

暂无评论

我要评论