Mysql元数据锁、行锁、MySQL事务介绍、InnoDB架构
元数据锁
行锁的意义和场景
记录锁和间隙锁
死锁原理和场景
事务的概念和四大特征ACID
Redolog的作用

元数据锁

MDL(MeteDataLock 5.5版本映入)元数据:也是一个表锁, 即表结构。当对表结构炒作的时候加DML的写锁,当DML(Data Manipluation Language 数据操作语言即insert、update、delete)操作的时候加DML读锁,该锁是MySQL自动加(就是防止在操作表数据的时候,表结构不能变化)。

  1. begin; -- 开启事务,其他会话将无法对该表结构产生影响
  2. select * from mylock; -- 此处selectmysql自动 DML读锁
  3. commit; -- 提交事务 或者 roolback 释放锁

行级锁

行写锁(读写和写锁互斥)
单纯的select 不加锁!select * from table where 。。。。 lock in share mode

  1. -- 行写锁(加写锁,不影响其他数据读取)
  2. -- select ... 查询不加锁,select ... lock in share mode 读锁。
  3. select * from mylock where id =1 for update;

共享读锁
排他写锁

记录锁

防止幻读(T1、T2读取一个字段,T2插入一条数据,T1再次查询后以前的不一致了)!
锁的是某一行的记录。主键指定,比如 where id=3 时表示该条记录查询是,无法操作DML

间隙锁(gap locks)

锁定记录前、记录中、记录后的行,在RR隔离级(可重复读)也是Mysql的默认隔离级。锁的时候两行之间的间隙(两行数据的缝)
image.png

  1. start transaction;
  2. -- 产生一个 123 456的间隙锁
  3. update gap_lock set number = 80 where id >1 and id <4;

Next-Key锁

记录锁+间隙锁

意向锁

将要发生锁的时候,跟别人说马上要去发起锁了!

两阶段锁

行锁加锁、解锁

  1. -- 查看行锁状态
  2. show status like 'innodb_row_loc%'
  3. -- 返回结果
  4. 'Innodb_row_lock_current_waits', '0'
  5. 'Innodb_row_lock_time ', '50602' -- 如果改行数字过大,表示并发有问题出现了很多锁定状态
  6. 'Innodb_row_lock_time_avg', '50602'
  7. 'Innodb_row_lock_time_max', '50602'
  8. 'Innodb_row_lock_waits', '1'
  9. -- 事务加锁
  10. begin;
  11. select * from users where id =1 lock in share mode -- 对改行加读锁
  12. rollback;
  13. -- 此时另外一个会话来更新该条记录,将阻塞
  14. update users set name = 'zdddd' where id=1
  15. -- 超时抛出异常:21:52:49 update users set name = 'zdddd' where id=1 Error Code: 2013.
  16. Lost connection to MySQL server during query 30.005 sec
  17. -- where中使用为添加索引的列作为查询条件时,加锁,将导致行锁升级为表锁
  18. begin;
  19. select * from dep where name ='部门4' lock in share mode;
  20. rollback;
  21. -- 在另外一个会话中,执行update,将出现阻塞(超时抛异常,释放该执行语句!)
  22. update dep set name = '部门4444' where id = 1;
  23. -- 如果在执行update where条件中的name为非索引列,该行锁将升级为表锁
  24. -- 因为没有加索引的列,在执行时扫描全表,扫描全表将对表加锁
  25. update dep set name='部门11aa' where name ='部分1111'

死锁

两个session互相等待对象释放资源之后,才能释放自己的资源,造成了死锁!Mysql发现死锁时自动结束其中一个,避免发生阻塞死锁!Deadlock found when trying to get lock;try restarting transaction!!!!

  1. begin;-- 会话1
  2. update a set name='11' where id =1;
  3. update a set name='22' where id =2;
  4. rollback;
  5. begin; -- 会话2
  6. update a set name ='222' where id = 2;
  7. update a set name ='111' where id =1;
  8. rollback;

事务

mysql事务在存储引擎实现,Innodb存储引擎,支持事务。要么都执行、要么都不执行。
事务四大特性ACID
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation):
事务之间互不影响,由mysql锁机制
MVCC机制来实现:多版本并发控制、优化读写性能、读不加锁、读写不冲突!
持久性(Durability)
显示的使用事务,begin、commit、rollback;

InnoDB架构


page 也叫脏页,因为和真实的数据文件是不一致的,还没有更新到数据文件中。这些数据会被先写入到redo-log-buffer中。

重做日志的落盘机制

redo-log Buffer 重做日志缓冲

重做日志保证了数据的可靠性,InnoDB采用了额Write Ahead Log(预写日志)策略,即当事务提交时,先写重做日志,然后再择时将脏页数据写入磁盘。如果发生宕机导致数据丢失,就通过重做日志进行数据恢复。
例如:insert into xxxx commit; Redo Log File 写成功则 Commit。
这个Redo-log在ib_logfile0、iblogfile1中(这两个大小默认8M,通过innodb_log_buffer_size控制大小)。

redo-log作用是实时保证在buffer pool中缓存的数据能够被保存下来,在mysql宕机后,重启后能够被记录到mysql的数据文件中(这个过程叫做redo-log落盘,这个机制是mysql默认的数据保存机制)。
image.png
在commit后数据将被真正写入到磁盘。

undo-log