Mysql

Mysql学习笔记

Posted by owl city on October 1, 2019
  • Create Date: 2019-12-03
  • Update Date: 2019-12-03

Mysql锁

锁类型 特点
表级锁 开销小,加锁快,不会出现死锁;锁粒度大,发生锁冲突的概率最高,并发度最低
行级锁 开销大,加锁慢,会出现死锁;锁粒度最小,发生锁冲突概率最低,并发度最高
页面锁 位于表锁和行锁之间,会出现死锁

MyISAM

  • mysql表级锁的锁模式 表共享读锁 表独占写锁

  • 如何加表锁

      Lock tables orders read local, order_detail read local;
      Select sum(total) from orders;
      Select sum(subtotal) from order_detail;
      Unlock tables;
    
    • 在lock的时候加local选项,是为了满足MyISAM表并发插入的情况下,允许其他用户在表尾并发插入记录.

    • 在用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,并且MySQL不支持锁升级。也就是说,在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行查询操作,而不能执行更新操作。其实,在自动加锁的情况下也基本如此,MyISAM总是一次获得SQL语句所需要的全部锁。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因。

  • MyISAM表的并发插入 MyISAM存储引擎有一个系统变量concurrent_insert,专门空值其并发插入的行为
    • 0 : 不允许并发插入
    • 1 : 如果MyISAM表中没有空洞(表中间没有被删除的行),它可以允许在一个进行读表的同时,另一个进行从表尾部插入记录,(默认设置)
    • 2 : 无论表中有没有空洞,都允许在表尾部并发插入记录
  • MyISAM的锁调度
    • 在一个进程请求某个表的读锁,另外一个进程请求表的写锁时,写进程先获得锁
    • 因为mysql会认为写请求比读请求更重要,这也是为什么MyISAM表不太适合有大量更新和查询操作应用的原因

InnoDB

Inno支持事务,采用了行级锁

  • 事务及其属性(ACID) 事务具有四个属性:
    • 原子性 : 事务是一个原子操作单元,其对数据的修改,要么全部执行,要不全都不执行
    • 一致性 : 在事务开始和完成时,数据必须保持一致状态
    • 隔离性 : 数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的”独立”环境下执行,以为着事务处理过程中的中间状态对外部是不可见的
    • 持久性 : 事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持
  • 并发事务处理带来的问题
    • 更新丢失 : 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题--最后的更新覆盖了由其他事务所做的更新
    • 脏读 : 一个事务正在对一条记录做修改,在这个事务完成并提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系
    • 不可重复读 : 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了
    • 可重复读: 在一个事务内,多次读取同一数据,另外一个事务对同一数据进行修改不会对第一个事务读取的数据产生影响
    • 幻读 : 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据
  • 事务隔离级别
    • 在读取数据前,对其进行加锁,阻止其他事务对数据进行修改
    • 不用加任何锁,通过一定的机制生成一个数据请求时间点的一致性数据快照,并用这个快照来提供一定级别的一致性读取.(多版本并发控制,MVCC或MCC)
    • 隔离级别越严格,并发副作用越小,但付出的代价越大
  • 四种隔离级别的比较 比较

  • 未提交读: 允许脏读,可能读取到其他回话中未提交事务修改的数据

  • 已提交读: 在一个事务内,多次读同一数据,在这个事务还没有结束时,另外一个事务对同一数据进行了修改,由于第二个事务的修改,第一个事务再次读到的数据与第一次的数据可能是不一致的,出现了不可重复读

InnoDB的行锁模式及枷锁方法

InnoDB实现了两种类型的行锁:

  • 共享锁(S) : 允许一个事务去读一行,阻止其他事务获得相同数据集的排他锁
  • 排他锁(X) : 允许获得排他锁的事务更新数据,阻止其他事务获得相同数据集的共享读锁和排他写锁
  • 意向排他锁 : 事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁
  • 意向排他锁 : 事务打算给数据行加排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁

行锁S,X锁有一些精确的细分,使锁的粒度更小,可以减少冲突

  • 间隙锁(Gap Lock), 只锁间隙
  • 记录锁(Record Lock), 只锁记录
  • Next-Key-Lock, 同时锁住记录和间隙
  • 插入意图锁(Insert Intention Lock), 插入时使用的锁