myisam存储引擎默认是表级锁
innodb存储引擎默认是行级锁
DBD存储引擎默认是页面锁
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
行级锁:开锁大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。
从上述特点可见,很难笼统的说哪种锁更好,只能就具体应用的特点来说哪种锁更合适!仅从锁的角度来说:表级锁
更于以查询为主,只有少量按索引条件更新数据的应用,如WEB应用;而行级锁则更适合于有大理按索引发更新少量
不同数据,同时又有并发查询的应用,如一些在线事务处理系统。
for update的锁表
InnoDB默认是行级别的锁,当有明确指定的主键时候,是行级锁。否则是表级别。
例子: 假设表foods ,存在有id跟name、status三个字段,id是主键,status有索引。
例1: (明确指定主键,并且有此记录,行级锁)
SELECT * FROM foods WHERE id=1 FOR UPDATE;
SELECT * FROM foods WHERE id=1 and name=’咖啡色的羊驼’ FOR UPDATE;
例2: (明确指定主键/索引,若查无此记录,无锁)
SELECT * FROM foods WHERE id=-1 FOR UPDATE;
例3: (无主键/索引,表级锁)
SELECT * FROM foods WHERE name=’咖啡色的羊驼’ FOR UPDATE;
例4: (主键/索引不明确,表级锁)
SELECT * FROM foods WHERE id<>’3’ FOR UPDATE;
SELECT * FROM foods WHERE id LIKE ‘3’ FOR UPDATE;
for update的注意点
1.for update 仅适用于InnoDB,并且必须开启事务,在begin与commit之间才生效。
2.要测试for update的锁表情况,可以利用MySQL的Command Mode,开启二个视窗来做测试。
for update的疑问点
当开启一个事务进行for update的时候,另一个事务也有for update的时候会一直等着,直到第一个事务结束吗?
答:会的。除非第一个事务commit或者rollback或者断开连接,第二个事务会立马拿到锁进行后面操作。
如果没查到记录会锁表吗?
答:会的。表级锁时,不管是否查询到记录,都会锁定表