一、锁的定义

  读锁(共享锁):是多事务可以并发读取数据的锁,但任何事务都被阻塞等待对该数据进行写操作和加写锁,直到已释放所有共享锁。

  写锁(排他锁):是指只有当前事务才可以进行读写操作的锁,则其他事务都被阻塞等待对该数据进行读写操作和加读写锁,直到已释放所有排他锁。

 

二、锁特点 

  •   表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低。
  •   行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
  •   页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。

 

三、MyISAM表锁

  MyISAM 存储引擎只支持表锁,MySQL 的表级锁有两种模式:表共享读锁(Table Read Lock)和表独占写锁(Table Write Lock)。

     读操作:某数据表被一事务加上读锁:

    本事务权限:只能读取当前数据表,不能写操作 当前数据表和读取其他数据表,否则报错;

    其他事务权限:也可以读所有数据表,但是不能写当前数据表(已被加读锁),如果对当前数据表执行写操作,则会阻塞直到释放所有锁;

  写操作:某数据表被一事务加上写锁:

    本事务权限:可以读写当前数据表,不能读写其他数据表,否则报错;

    其他事务权限:阻塞读写当前数据表,直到释放所有锁;

  读锁和写锁都是阻塞锁:例如A对数据表增加了写锁,如果B请求对数据表加写锁,此时B的加锁请求会一直处于阻塞状态,直到A释放了对表的锁,B才加锁成功获取到结果。

 

四、表锁的加锁/解锁方式

  MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作 (UPDATEDELETEINSERT 等)前,会自动给涉及的表加写锁;因此,用户一般不需要直接用LOCK TABLE命令给MyISAM表显式加锁。

  锁表:lock tables tbl_name read | wrinte,tbl_name1 read | wrinte,

  解锁表:unlock table

  查看表加锁状态:show open tables like '%tbl_name%';

  

   分析表锁命令:show status like 'table_locks%';

   注意:当某事务在执行 LOCK TABLE 后,只能访问加锁的这些表,该事务不能访问未加锁的表,其他事务可以访问未加锁的表;

  此外,Myisam的读写锁调度是写优先,因此Myisam不适合做写为主表的引擎,因为写锁后其他线程不能做任何操作,大量更新会使查询很难得到锁,从而造成永远堵塞。

 

五、Innodb行锁

   行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。有可能会出现死锁的情况。行级锁也分为共享锁和排他锁。

 

六、Innodb 行加锁方式:

  共享锁用法:select ... where id=1|2|3... lock in share mode;

  排它锁用法: select ... where id=1|2|3... for update;

 

七、死锁

   MyISAM中是不会产生死锁的,因为MyISAM总是一次性获得所需的全部锁,要么全部满足,要么全部等待。而在InnoDB中,锁是逐步获得的,就造成了死锁的可能。

​ 在InnoDB中,行级锁并不是直接锁记录,而是锁索引。索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引,MySQL会先锁定该非主键索引,再锁定相关的主键索引。 当两个事务同时执行,一个锁住了主键索引,在等待其他相关索引。另一个锁定了非主键索引,在等待主键索引。这样就会发生死锁。

 

八、事务( myisam引擎不支持事务, innodb和BDB引擎支持)

  事务的4个特性ACID: 原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability

 

  以银行汇款为例,张三给李四转款300.

    原子性: 是指某几句sql的影响,要么都发生,要么都不发生:张三减300, 李四+300 , insert银行流水, 3个操作,必须都完成,或都不产生效果.

    一致性: 事务前后的数据,保持业务上的合理一致 (汇款前)张三的余额+李四的余额  ====== (汇款后) 张三的余额+李四余额

  隔离性: 在事务进行过程中, 其他事务,看不到此事务的任何效果.

  持久性: 事务一旦发生,不能取消. 只能通过补偿性事务,来抵消效果.

 

   事务的使用流程:

      开启事务   start transaction

     执行查询   xxxx

     提交事务/回滚事务. commit / rollback

   事务级别设置:set session transaction isolation level [read uncommitted |  read committed | repeatable read |serializable]

   查看事务级别: show variables like '%isolation%';

   事务级别划分:

    read uncommitted:  读未提交的事务内容,显然不符原子性, 称为”脏读”. 在业务中,没人这么用.(最低级别)

    read commited:   在一个事务进行过程中, 读不到另一个进行事务的操作,但是,可以读到另一个结束事务的操作影响.(语句级别)

    repeatable read: 可重复读,即在一个事务过程中,所有信息都来自事务开始那一瞬间的信息,不受其他已提交事务的影响. (大多数的系统,用此隔离级别,事务级别)

    serializeable 串行化  , 所有的事务,必须编号,按顺序一个一个来执行,也就取消了冲突的可能.这样隔离级别最高,但事务相互等待的等待长. 在实用的也不是很多.(最高级别)

    

 

 

 

 

posted on 2020-12-16 18:28  鸥海  阅读(82)  评论(0编辑  收藏  举报