zoukankan      html  css  js  c++  java
  • 数据库事务/索引/存储引擎/锁

    SQL 标准定义了四个隔离级别:

    • READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。

    • READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。

    • REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。

    • SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。

    MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)==========》通过SELECT @@tx_isolation;命令来查看

                 InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key Lock 锁算法

    脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚

     不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其他事务修改的提交而引起的。

        例如:事务B中对某个查询执行两次,当第一次执行完时,事务A对其数据进行了修改。事务B中再次查询时,数据发生了改变

    幻读,是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样.

    《《《=========================》》》

    为什么索引能提高查询速度:

    MySQL的基本存储结构是页 (记录都存在页里边)

    • 各个数据页可以组成一个双向链表

    • 每个数据页中的记录又可以组成一个单向链表

    - 每个数据页都会为存储在它里边儿的记录生成一个页目录,在通过主键查找某条记录的时候可以在页目录中使用二分法快速定位到对应的槽,然后再遍历该槽对应分组中的记录即可快速找到指定的记录
    - 以其他列(非主键)作为搜索条件:只能从最小记录开始依次遍历单链表中的每条记录。

    索引做了些什么可以让我们查询加快速度呢?其实就是将无序的数据变成有序(相对):===》二分查找,时间复杂度近似为O(logn)

    注意避免冗余索引

     冗余索引指的是索引的功能相同,能够命中就肯定能命中 ,那么 就是冗余索引如(name,city )和(name )这两个索引就是冗余索引,能够命中后者的查询肯定是能够命中前者的 在大多数情况下,都应该尽量扩展已有的索引而不是创建新索引。

    =======》查看成员索引--》可以通过查询 sys 库的 schema_redundant_indexes 表来查看冗余索引

    1.添加PRIMARY KEY(主键索引)====》ALTER TABLE `table_name` ADD PRIMARY KEY ( `column` ) 

    2.添加UNIQUE(唯一索引)===》ALTER TABLE `table_name` ADD UNIQUE ( `column` )

    3.添加INDEX(普通索引)====》ALTER TABLE `table_name` ADD INDEX index_name ( `column` )

    4.添加FULLTEXT(全文索引)===》ALTER TABLE `table_name` ADD FULLTEXT ( `column`)  【全文索引为在字符串数据中进行复杂的词搜索提供有效支持。全文索引存储关于重要词和这些词在特定列中的位置的信息。全文查询利用这些信息,可快速搜索包含具体某个词或一组词的行。

    5.添加多列索引===》ALTER TABLE `table_name` ADD INDEX index_name ( `column1`, `column2`, `column3` )

    《==========》

    存储引擎

    查看MySQL提供的所有存储引擎========》mysql> show engines;

    查看MySQL当前默认的存储引擎=========》mysql> show variables like '%storage_engine%';

    查看表的存储引擎=========》show table status like "table_name" ;

    MyISAM和InnoDB区别

    MyISAM是MySQL的默认数据库引擎(5.5版之前)。虽然性能极佳,而且提供了大量的特性,包括全文索引、压缩、空间函数等,但MyISAM不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复。不过,5.5版本之后,MySQL引入了InnoDB(事务性数据库引擎),MySQL 5.5版本后默认的存储引擎为InnoDB。

    大多数时候我们使用的都是 InnoDB 存储引擎,但是在某些情况下使用 MyISAM 也是合适的比如读密集的情况下。

    两者的对比:

    1. 是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁。

    2. 是否支持事务和崩溃后的安全恢复:MyISAM 强调的是性能,每次查询具有原子性,其执行比InnoDB类型更快,但是不提供事务支持。但是InnoDB 提供事务支持事务,外部键等高级数据库功能。具有事务(commit)、回滚(rollback)和崩溃修复能力(crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。

    3. 是否支持外键: MyISAM不支持,而InnoDB支持。

    4. 是否支持MVCC :仅 InnoDB 支持。应对高并发事务, MVCC比单纯的加锁更高效;MVCC只在 READ COMMITTED 和 REPEATABLE READ 两个隔离级别下工作;MVCC可以使用 乐观(optimistic)锁 和 悲观(pessimistic)锁来实现;各数据库中MVCC实现并不统一。

    乐观锁与悲观锁的区别

    悲观锁:总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。

    注:===》传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronizedReentrantLock等独占锁就是悲观锁思想的实现。

    乐观锁:总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

    乐观锁一般会使用版本号机制或CAS算法实现。=====》

    1. 版本号机制

    一般是在数据表中加上一个数据版本号version字段,表示数据被修改的次数,当数据被修改时,version值会加一。当线程A要更新数据值时,在读取数据的同时也会读取version值,在提交更新时,若刚才读取到的version值为当前数据库中的version值相等时才更新,否则重试更新操作,直到更新成功。

    2. CAS算法

    compare and swap(比较与交换),是一种有名的无锁算法。无锁编程,即不使用锁的情况下实现多线程之间的变量同步,也就是在没有线程被阻塞的情况下实现变量的同步,所以也叫非阻塞同步(Non-blocking Synchronization)。CAS算法涉及到三个操作数

    • 需要读写的内存值 V

    • 进行比较的值 A

    • 拟写入的新值 B

    锁机制与InnoDB锁算法

    MyISAM和InnoDB存储引擎使用的锁:

    • MyISAM 采用表级锁(table-level locking)。

    • InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁

    表级锁和行级锁对比:

      • 表级锁: Mysql中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。

      • 行级锁: Mysql中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。

    InnoDB存储引擎的锁的算法有三种:

    • Record lock:单个行记录上的锁

    • Gap lock:间隙锁,锁定一个范围,不包括记录本身

    • Next-key lock:record+gap 锁定一个范围,包含记录本身

    相关知识点:

    • innodb对于行的查询使用next-key lock

    • Next-locking keying为了解决Phantom Problem幻读问题

    • 当查询的索引含有唯一属性时,将next-key lock降级为record key

    • Gap锁设计的目的是为了阻止多个事务将记录插入到同一范围内,而这会导致幻读问题的产生

    • 有两种方式显式关闭gap锁:(除了外键约束和唯一性检查外,其余情况仅使用record lock) A. 将事务隔离级别设置为RC B. 将参数innodb_locks_unsafe_for_binlog设置为1

  • 相关阅读:
    移动端 提交按钮呗软键盘挤上去的问题解决
    jenkins创建项目API踩坑记
    backstage使用笔记(2)- 跨域代理设置
    backstage使用笔记(1)- 项目的搭建和插件的创建
    什么是强缓存,什么是协商缓存?
    关于antd英文文案切换为中文
    记解决遇到自己电脑看线上项目没问题,别的同事电脑看线上项目有问题的疑难杂症
    vue.js组件传值
    Vue.js组件
    关于Object.keys()和for in的区别
  • 原文地址:https://www.cnblogs.com/KL2016/p/14557241.html
Copyright © 2011-2022 走看看