mysql锁机制分为表锁和行锁,其中行锁又包括了共享锁与排他锁。
又称为读锁(S锁),当有多个事务时,多个事务对于同一数据可以共享一个锁,都能访问到数据,但是其他事务只能读不能写。
又称为写锁(X锁),当有多个事务时,排他锁不能与其他锁并存,一个事务获取了一行数据的排他锁,其他事务就不能再获取该行的其他锁,包括共享锁与排他锁。 但是获取排他锁的事务是可以对数据进行读取和修改的。
共享锁就是多个事务只能读数据不能改数据。排他锁是指一个事务在一行数据加上排他锁后,其他事务不能再在其上面加其他的锁。Innodb引擎默认的修改数据语句,update,insert,delete都会自动给涉及到的数据加上排他锁,select语句默认不加锁,如果加共享锁可以用select ... lock in share mode语句。 如果加排他锁可以使用select ... for update语句。 加过排他锁的数据行在其他事务中是不能修改数据的,也不能通过for update和lock in share mode锁的方式查询数据,但可以直接通过select ... from ...查询数据,因为普通查询没有任何锁机制。
首先关闭自动提交:
测试数据如下(一切从简哈),然后打开两个查询窗口。
首先进行共享锁测试: 下面的都是先执行左边再执行右边
共享锁与共享锁:
两个窗口都使用共享锁查询,能够共享这条数据。
共享锁与排他锁:
当一条数据别共享锁锁住时,不能对数据进行修改,排他锁不能与共享锁共存,会处于堵塞状态等待共享锁事务提交。
事务提交后就可以进行修改了
共享锁与普通查询:
都能查询到数据
再进行排他锁测试: 下面的都是先执行左边再执行右边
排他锁与排他锁:
排他锁与共享锁:
可以看到都处于阻塞状态,id=1的数据已经被加上了排他锁,必须等到锁释放才能加上别的锁。
不加锁的查询是可以查询到数据的,因为没有锁机制不与排他锁互斥。
查询其他行也可以查询到数据。
InnoDB所用的表级锁,其设计目的主要是为了在一个事务中揭示下一步将要被请求的锁的类型。
InnoDB中的两个表锁:
意向共享锁(IS):表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁
意向排他锁(IX):类似上面,表示事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须先取得该表的IX锁。
意向锁是InnoDB自动加的,不需要用户干预。
MySQL表级锁分为读锁和写锁。
用法:LOCK TABLE table_name [ AS alias_name ] READ
释放锁使用UNLOCK tables.可以为表使用别名,如果一旦使用别名在使用的时候也必须采用别名。成功申请读锁的前提是当前没有线程对该表使用写锁,否则该语句会被阻塞。申请读锁成功后,其他线程也可以对该表进行读操作,但不允许有线程对其进行写操作,就算是当前线程也不允许。当锁住了A表之后,就只能对A表进行读操作,对其他表进行读操作会出现错误(tablename was not locked with LOCK TABLES)
用法: LOCK TABLE table_name [AS alias_name] [ LOW_PRIORITY ] WRITE
同样也可以使用别名,与读锁不同的是,写锁中可以指定锁的优先级。LOW_PRIORITY是一种比读锁更低优先级的锁,当多个线程同时申请多种锁(LOW_PRIORITY,READ,WRITE)时,LOW_PRIORITY的优先级最低。读锁申请成功的前提是没有线程对表加读锁和其他写锁,否则会被阻塞。
表级锁在MyISAM和innoDB中都有用到,创建锁的开销小,不会出现死锁,由于锁定的是整张表,所以并发度低。当需要频繁对大部分数据做 GROUP BY 操作或者需要频繁扫描整个表时,推荐使用表级锁。
结束。
我的其他关于mysql的博客,可以看下哦。
mysql架构与存储引擎 (Myisam与Inoodb)