这里写目录标题

  • 一。锁类型总结图
  • 二.锁类型
  • 1.乐观锁
  • 1.1实现
  • 2.悲观锁
  • 2.1. 表锁
  • 2.1.1什么时候使用表锁
  • 2.1.2 在InnoDB下 ,使用表锁要注意以下两点。
  • 2.1.3实现
  • 2.2 行锁
  • 2.2.1共享锁
  • A.解释
  • B.实现实现:lock in share mode
  • 2.2.2 排它锁。
  • A.解释
  • B.实现:for update
  • C.其他
  • D.间隙锁


一。锁类型总结图

mysql 中有哪些锁 mysql锁有几种_死锁

二.锁类型

1.乐观锁

乐观锁不是数据库自带的,需要我们自己去实现,假设丢失更新不一定发生。

1.1实现

增加一个version字段,更新数据,version+1
提交数据前判断version是否一致

2.悲观锁

2.1. 表锁

不会出现死锁,发生锁冲突几率高,并发低。

2.1.1什么时候使用表锁

对于InnoDB表,在绝大部分情况下都应该使用行级锁,因为事务和行锁往往是我们之所以选择InnoDB表的理由。但在个另特殊事务中,也可以考虑使用表级锁。

第一种情况是:
事务需要更新大部分或全部数据,表又比较大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能造成其他事务长时间锁等待和锁冲突,这种情况下可以考虑使用表锁来提高该事务的执行速度。

第二种情况是:
事务涉及多个表,比较复杂,很可能引起死锁,造成大量事务回滚。这种情况也可以考虑一次性锁定事务涉及的表,从而避免死锁、减少数据库因事务回滚带来的开销。

2.1.2 在InnoDB下 ,使用表锁要注意以下两点。

(1)使用LOCK TALBES虽然可以给InnoDB加表级锁,但必须说明的是,表锁不是由InnoDB存储引擎层管理的,而是由其上一层MySQL Server负责的,仅当autocommit=0、innodb_table_lock=1(默认设置)时,InnoDB层才能知道MySQL加的表锁,MySQL Server才能感知InnoDB加的行锁,这种情况下,InnoDB才能自动识别涉及表级锁的死锁;否则,InnoDB将无法自动检测并处理这种死锁。

(2)在用LOCAK TABLES对InnoDB锁时要注意,要将AUTOCOMMIT设为0,否则MySQL不会给表加锁;事务结束前,不要用UNLOCAK TABLES释放表锁,因为UNLOCK TABLES会隐含地提交事务;COMMIT或ROLLBACK产不能释放用LOCAK TABLES加的表级锁,必须用UNLOCK TABLES释放表锁,正确的方式见如下语句。

例如,如果需要写表t1并从表t读,可以按如下做:

SET AUTOCOMMIT=0;
LOCAK TABLES t1 WRITE, t2 READ, ...;
[do something with tables t1 and here];
COMMIT;
UNLOCK TABLES;

2.1.3实现

在 RDS MySQL 实例日常使用中,有些情况下会发现出现 Innodb 表级锁等待的情况,下面列出常见的2个原因。

  1. 显式 lock table

执行了 lock tables tab_name read; 导致 DML 会话等待在表的表级锁上。

lock tables tab_name read;
  1. 隐式 lock table

mysqldump 使用默认参数进行数据导出时,会默认的开启 –lock-tables 选项,进而导致导出表上的DML操作等待在表级锁上。

对于 mysqldump 方式的导出,建议在业务低峰期进行导出,并且设置 –single-transaction 选项进行 Innodb 引擎表导出,避免出现 Innodb 表级锁等待的情况。

2.2 行锁

会出现死锁,发生锁冲突几率低,并发高
行锁分 共享锁 和 排它锁。
注意几点:

1.行锁必须有索引才能实现,否则会自动锁全表,那么就不是行锁了。

2.两个事务不能锁同一个索引,例如:
 事务A先执行:  
select math from zje where math>60 for update;  

事务B再执行:  
select math from zje where math<60 for update;  
这样的话,事务B是会阻塞的。如果事务B把 math索引换成其他索引就不会阻塞,但注意,换成其他索引锁住的行不能和math索引锁住的行有重复。

2.2.1共享锁

其他事物可读不可写

A.解释

共享锁 又称 s锁,读锁
若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,
其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。
这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

B.实现实现:lock in share mode

select * from table   lock in share mode

2.2.2 排它锁。

其他事物不可读不可写

A.解释

排他锁又称 x锁,写锁
若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,
其他事务不能再对A加任何锁,直到T释放A上的锁。
这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

B.实现:for update

select math from zje where math >60 for update;

C.其他

insert ,delete , update在事务中都会自动默认加上排它锁

D.间隙锁

又称gap锁

mysql 中有哪些锁 mysql锁有几种_死锁_02


其实这个多出来的GAP锁,就是RR隔离级别,相对于RC隔离级别,不会出现幻读的关键。确实,GAP锁锁住的位置,也不是记录本身,而是两条记录之间的GAP。所谓幻读,就是同一个事务,连续做两次当前读 (例如:select * from t1 where id = 10 for update;),那么这两次当前读返回的是完全相同的记录 (记录数量一致,记录本身也一致),第二次的当前读,不会比第一次返回更多的记录 (幻象)。

如何保证两次当前读返回一致的记录,那就需要在第一次当前读与第二次当前读之间,其他的事务不会插入新的满足条件的记录并提交。为了实现这个功能,GAP锁应运而生。