zoukankan      html  css  js  c++  java
  • mysql 存储引擎 innodb 学习复习 之 锁

    由于书是从图书馆借来的,记下一些学习的过程,便于以后查看

    1. 锁是数据库区别于文件系统的重要特性之1,锁机制用于管理对共享文件的并发访问

       innodb使用的是行级锁

       myisam,使用的是表级锁,在并发条件下,读操作没有问题,但是并发插入会有性能上的影响

       sql server 2005之前的版本都是页级锁的,相对于myisam言,并发访问上性能有所提高,在2005以及之后,sql server 支持乐观并发和悲观并发,在乐观并发下执行行级锁,但实现方式和与innodb不相同,在sql server中,锁是一种稀有的资源,而在mysql innodb中,锁没有相关的开销,可以同时得到并发性和一致性

    2. innodb的锁类型

        共享锁和排他锁

       共享锁 (S Lock): 允许事务读一行数据

       排他锁(X Lock):允许事务写或者修改一行数据

      ,可以在一行上使多个S锁,但是只要有X锁,就不能在加其他的锁了

      innodb存储引擎支持多粒度锁定,这种锁定允许在表级和行级上的锁同时存在,为了支持在不同粒度上架锁,innodb  提供了一种意向锁,意向锁是表级锁,且分为 意向共享锁和排他共享锁

    3.  一致性非锁定读

        一致性非锁定读,是指innodb通过行多版本控制技术的方式来读取数据库中的数据,入如果读取的数据正在进行删除或者更新,这时读取操作不会因此等待行上的锁释放,而会去读取行的一个快照(快照指的是该行之前的版本的数据,该实现通过undo段实现),而因为undo段是用来在事务中回滚数据的,因此快照没有额外的开销,读取快照不需要加锁

        可以看出的是,一致性非锁定读,大大提高了数据读取的并发性,在innodb中,只是默认的方式,即读取不会占用和等待表上的锁,但是,在事务不同的隔离级别下,读取方式还是有所不同的,并不是每一个隔离级别下读取都是一致性的读。

    4. 自增长和锁

     在innodb的内存结构中,对每一个含有自增长值的表都有一个自增长计数器,对含有自增长计数器的表进行插入时,这个计数器会被初始化,然后使用:

       select max(auto_inc_col) from table for update ,插入操作接着会依据这个自增长的计数器值加1赋予自增长列,这种实现方式称为:AUTO_INC Locking ,这种锁实际上是一种表级锁机制,为了提高插入的性能,锁不是在一个事务完成后才释放,而是在完成对自增长的值插入之后就立即释放,锁住的时间越短越好

      但是这种方式,在大量的插入操作中还是会有性能的问题,1) 对于自增长型的列的插入性能较差,必须等待前一个插入完成后才能插入下一个(虽然不用等待事务完成),2)对于insert select 的大数据量的插入,会影响插入的性能,因为另一个事务的插入可能会被阻塞

       

       从mysql 5.1.22起,innodb提供了一种 轻量级互斥量的自增长实现机制,便于提高并发的性能,使用一个参数 :innodb_autoinc_lock_mode,默认值为1

      在innodb 中,自增长值的列必须是索引,并且是索引的第一列,如果是第2列也会报错,另外,myisam是表级锁,不用考虑自增长并发插入

    5. 外键和锁

       外键主要用于引用完整性的检查,在innodb中,如果没有对外键列加索引,innodb会隐式的对其加索引,这样可以避免表级锁 

       对于外键的插入,首先要查询父表中的记录,即select 父表,但对父表的select,不使用一致性非锁定读,因为这样会发生数据不一致性,innodb使用的是select ... lock in share mode ,主动对父表加一个S锁,这样,如果在父表上已经加了一个X锁,子表的操作就会被阻塞

    6. 锁的算法

      innodb中有3种行锁的算法设计

      1) Record lock,单个行记录上的锁

      2)Gap Lock 间接锁,锁定的是一个范围,但不包含记录本身

      3) Next-key Lock : = Record lock + Gap lock ,锁定一个范围,并且包含记录本身

    Record lock 总是会锁住索引记录,如果在建立存储引擎表时没有设置任何索引,innodb会使用隐式的主键进行锁定

    在Next-key lock 算法下,对于行的查询,都是这种方式,对于不同的sql 查询,可能设置共享的 Next-key lock,或者 排他的 Next-key lock

    7.  锁问题

    锁会并发访问带来了性能上的提高,但是同时也会带来几个问题。1) 丢失更新。2) 脏读 3)不可重复读

    1) 丢失更新

    2) 脏读,指的是在不同事务下,可以读到另一个事务未提交的数据

    3) 不可重复读,指的是在同一个事务中多次的读取同一个数据,在这个事务还没有结束之前,另外一个事务修改了这个数据,这是,在同一个事务的两次读之间,由于第2个事务的修改导致第一次事务两次读数据不同

    脏数据和脏页的区别:

    脏页指的是缓存池中已经修改但是还没有刷新到磁盘文件中,即数据库内存中的页和磁盘内存中的页数据是不一致的。而脏数据是指缓冲池中被修改的数据,但是还没有被提交。

    对于脏页的读取是正常的,这并不影响数据的一致性,并且还因为是异步的,可以带来性能上的提高,而脏数据的读取,是一个事务读取到了另一个事务的数据,显然违反了事务的隔离性

    脏读和不可重复读的区别:

    脏读是读到了未提交的数据,而不可重复读读的是已经提交的,但是违反了事务的一致性要求 

    8. 阻塞

    因为不同锁之间的兼容性,在有些时候,一个事务中的锁需要等待另一个事务中的锁释放它所占用的资源,在innodb中使用的是Mutex数据结构来实现,在访问之前,需要使用mutex_enter函数进行申请,在资源访问完成之后立即执行mutex_exit(),但一个资源被一个事务占用时,另一个事务执行mutex_enter函数会发生阻塞

      innodb中,参数innodb_lock_wait_timeout用来设置超时的时间

    9. 死锁

    如果程序是串行的,那么搜索是不可能的,死锁只发生在并发访问情况下,innodb 中有一个后台thread,用来负责查看所有可能的死锁问题,并告知用户

    10 锁升级

    指的是当前锁的粒度降低,eg :将行级锁升级为 页级,页级升级为 表级

    在innodb中,锁升级不会带来性能上的问题,1个锁的开销和100000个锁开销是相同的 

       

  • 相关阅读:
    探索式测试实践之路
    管理是什么?真正的管理者是,“管”+“理”!
    JavaScript中的函数式编程
    node js的终端中 console.log 嵌套对象会被折叠的问题
    apt-get install的默认安装路径
    nodejs 事件循环 试题思考
    仅20行的JavaScript模板引擎
    js 驼峰命名转烤串
    git reset 进阶
    linux 拷贝文本到剪切板
  • 原文地址:https://www.cnblogs.com/hitwtx/p/2174297.html
Copyright © 2011-2022 走看看