zoukankan      html  css  js  c++  java
  • MySQL 并发控制概述

    禁止码迷,布布扣,豌豆代理,码农教程,爱码网等第三方爬虫网站爬取!

    MySQL 逻辑架构

    Mysql 逻辑架构可以分为 3 层,最上层的服务对于大多数基于网络的工具或服务都有类似的架构,例如连接处理、授权认证、安全等等。
    大多数 MySQL 的核心服务功能都在第二层,例如查询解析、优化、缓存即所有内置函数。所有跨存储引擎的功能也在第二层实现,例如存储过程、触发器、视图等功能。
    第三层包含了存储引擎,负责 MySQL 中数据的存储和提取。每个引擎都有其优势和劣势,服务器通过 API 与存储引擎进行通信。

    并发控制

    当有多个查询在同一时刻修改数据,就会引发并发控制的问题,这个问题的解法就是并发控制

    读写锁

    处理兵法的读或写时,可以通过一个由 2 种类型的锁组成的锁系统来解决,2 种锁被称之为共享锁排他锁,或读锁写锁。读锁是共享的,多个客户在同一时刻可以同时读取一个资源,互不干扰。写锁是排他的,写锁会阻塞其他的写锁和读锁,这样就能确保在一段时间内只有一个用户进行写入。
    当某个用户在修改某一部分数据时,MySQL 会通过锁定防止其他用户读取同一数据。

    锁粒度

    尽量只锁定需要修改的部分,而不是所有的资源,会带来更好的贡献资源并发性。在给定的资源上,锁定的数据量越少,则系统的并发程度越高。加锁同样需要消耗资源,如果系统花费大量时间来管理所,则存储数据的资源就会受影响,进而影响系统的性能。每种 MySQL 存储引擎都可以是实现自己的锁策略和锁粒度,所谓锁策略就是在锁的开销和数据安全性之间的平衡策略。将锁粒度控制在某个级别,可以为某些特定场景提供更好的性能,但是也会失去对其他场景的支持。

    表锁

    表锁是 MySQL 中开销最小的锁策略,表锁将锁定整张表。用户对表进行增删改等操作时,需要先获得写锁,写锁会阻塞其他用户对表的读写操作。没有写锁时其他用户才能获得读锁,读锁之间不会进行阻塞。

    行级锁

    行级锁可以锁定某一行,它可以最大限度地支持并发处理,同时锁的开销也会增大。

    事务

    事务是一组原子性的 SQL 查询,可以理解为一个独立的工作单元。事物的特点是:如果任何一条语句因崩溃或其他原因无法执行,则所有的语句都不会执行。事务机制的存在非常必要,如果一个系统允许不完整的操作制造的数据存在,则数据库中将充满大量错误的数据,这种情况往往不能被容忍。

    ACID

    一个良好的事务处理系统,必须具备 ACID 特性,分别是原子性、一致性、隔离性和持久性。

    1. 原子性:对于一个事务而言,不可能只执行其中的一部分;
    2. 一致性:数据库总是从一个一致性的状态,转换到另一个一致性状态;
    3. 隔离性:事务所做的所有修改,在最终提交之前对其他事物都是不可见的;
    4. 持久性:一旦事务提交,则其所做的修改就会永久保存到数据库中。

    一个实现 ACID 的数据库,相比没有实现的数据库会需要更强的 CPU 处理能力、更大的内存和更多的磁盘空间。对于一些不需要事务的查询类应用,选择一个非事务型的存储引擎,可以得到更高的性能。

    隔离级别

    对于隔离性,SQL 在标准中定义了 4 种隔离级别。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。

    1. READ UNCOMMITTED:未提交读,事务的修改即使没有提交,对其他事物也都是可见的。事务可以读取未提交的数据的行为,被称之为脏读
    2. READ COMMITTEN:提交读,一个失误从开始到提交之前,所做的任何修改对其他事物都是不可见的。因为 2 次相同的查询可能得到不同的结果,该级别也可以称之为不可重复读
    3. REPEATABLE READ:可重复读:在同一个事务中,多次读取相同记录的结果是一样的。但是这种级别无法阻止幻读的出现,所谓幻读就是某个事物在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录。可重复读是 MySQL 的默认隔离级别。
    4. SERIALIZABLE:可串行化,该级别可以强制事务串行执行。在读取的每一行数据都加上所,可能导致大量的超时和锁争用的问题。

    死锁

    死锁指两个以上的事务在同一资源上相互占用,并且请求锁定对方占用的资源导致的恶性循环现象。死锁可能会因为数据的冲突而产生,也会由存储引擎的实现方式导致。
    为了解决这类问题,数据库系统实现了各种死锁检测和死锁超时机制,例如 InnoDB 存储引擎能够检测到死锁的循环依赖,并且返回一个错误。InnoDB 处理死锁使用了较为简单的算法:将持有最少行级排他锁的事物回滚

    事务日志

    事务日志可以使存储引擎修改表的数据时,只需要修改其内存拷贝,然后把该数据的修改行为记录到硬盘上的事务日志中。这种手法采用追加的形式,不需要每次都把修改的数据都保存到硬盘上。事务日志持久化时,内存中被修改的数据在后台会慢慢保存入磁盘。
    若数据的修改已经记录到日志中,而数据本身还没有保存到磁盘,此时即使系统崩溃存储引擎也能在重启时恢复数据。

    MySQL 事务

    MySQL 默认采用自动提交模式,如果不是显式地开始一个事务,则每个查询都会被认为是一个事务执行提交操作。可以通过设置 AUTOCOMMIT 变量来启用或禁用:

    SHOW VARIABLES LIKE 'AUTOCOMMIT';
    SET AUTOCOMMIT = 1;
    

    MySQL 可以通过该命令设置隔离级别,MySQL 可以识别 4 种级别。

    SET TRANSACTION ISOLATION LEVEL
    

    事务是由下层存储引擎实现的,因此一个事务使用多种存储引擎是不可靠的。例如事务需要回滚,非事务型的表上的变更无法撤销,这就导致数据库处于不一致的状态。

    隐式锁与显式锁

    InnoDB 采用两阶段锁定协议,事务执行时随时都可以执行锁定,锁只有在执行 COMMIT 或者 ROLLBACK 时才会释放,并且是同时释放所有的锁,这类锁都是隐式锁定。无论是使用什么存储引擎,都不建议使用 LOCK TABLES 指定显式锁。

    多版本并发控制

    MVCC 可以认为是行级锁的一个变种,在很多情况下避免了枷锁的操作,大多数 MVCC 都实现了非阻塞的读操作,写操作也只锁定必要的行。MVCC 是通过保存数据在某个时间点的快照来实现,不管执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务在同一时刻对于同一张表看到的数据可能不一致。
    InnoDB 的 MVCC 是通过每行记录后面保存 2 个隐藏的列来实现,一个列保存行的创建时间,一个列保存行的过期时间。时间的记录形式是系统版本号,每开始一个新事务系统版本号就会自动递增。保存系统版本号使得大部分读操作都不用加锁,这么做使得读取数据操作简单且性能好。
    MVCC 仅兼容可重复读和提交读这 2 中隔离级别。

    参考资料

    《高性能 MySQL》[美]Baron Schwartz,Peter Zaitsev,Vadim Tkachenko 著,宁海元、周振兴、彭立勋、翟卫祥 等译,电子工业出版社
    《MySQL Crash Course》[英] Ben Forta 著,刘晓霞 钟鸣 译,人民邮电出版社

  • 相关阅读:
    Enterprise Library 2.0 技巧(4):如何用编程的方法来配置Logging Application Block
    Castle IOC容器实践之EnterpriseLibrary Configuration Facility
    Castle开发系列文章上了Castle的官方网站
    DataGridView也泛型?——一个不错的DataGridView控件
    Enterprise Library for .NET Framework 3.0 what would you like to see?
    设计是否可以更合理一点?——关于ORM中业务实体的讨论
    Enterprise Library 2.0 技巧(2):如何将配置信息保存到数据库中
    关于Castle IOC容器自动装配的问题
    数据库重构与数据库单元测试
    BLINQ初体验
  • 原文地址:https://www.cnblogs.com/linfangnan/p/13275257.html
Copyright © 2011-2022 走看看