高性能MySql-并发与事务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010391342/article/details/89646965

SQL语句的执行流程

无论何时,只要有多个查询需要在同一个时刻修改数据时,就会有并发问题。MySql主要在服务器层存储引擎层进行并发控制。

假设数据库中国一张邮箱表,每个邮件都是一条记录。如果某个客户正在读取邮箱,同时其他客户试图在删除邮箱表中的某一条数据。这个时候,读取的结构就是不确定的了。在MySql中会通过锁定防止其它用户读取同一数据。大多数时候,MySQL锁的内部管理都是透明的。

MySQL锁的粒度

  • 每种MySql引擎都可以实现自己的锁策略和锁粒度,将锁粒度固定在某个级别,可以为某些特定的场景提供更好的性能。

表锁(table lock)

  • 表锁是mysql中最基本的锁略,并且是开销最小的策略。它会锁定整个表,一个用户在对表进行写操作(插入、删除、更新等)前,需要先获得写锁,这会阻塞其他用户对该表的所有读写操作。只有没有写锁时,其他读取的用户才能获得读锁,读锁之间是不相互阻塞的。
  • 在特定的场景中,表锁也可能有良好的性能。例如,READ L0CAL 表锁支持某些类型的并发写操作。另外,写锁也比读锁有更高的优先级,因此-一个写锁请求可能会被插入到读
    锁队列的前面(写锁可以插入到锁队列中读锁的前面,反之读锁则不能插入到写锁的前
    面)。
  • 尽管存储引擎可以管理自己的锁,MySQL本身还是会使用各种有效的表锁来实现不同
    的目的。例如,服务器会为诸如ALTER TABLE 之类的语句使用表锁,而忽略存储引擎的
    锁机制。

行级锁(row lock)

  • 行级锁可以最大程度地支持并发处理(同时也带来了最大的锁开销)。
  • InnoDBXtraDB,以及其他一些存储引擎中实现了行级锁。
  • 行级锁只在存储引擎层实现,而MySQL服务器层没有实现。服务器层完全不了解存储引擎中的锁实现。

MySQL的事务

事务特性

  • A(原子性)事务的各步操作是不可分的,保证一系列的操作要么都完成,要么都不完成;
  • C(一致性)事务完成,数据必须处于一致的状态;
  • I(隔离性)对数据进行修改的所有并发事务彼此之间是相互隔离,这表明事务必须是独立的,不应以任何方式依赖或影响其他事务;
  • D(持久性)表示事务对数据处理结束后,对数据更改必须持久化,不管是事务成功还是回滚。事务日志都能够保持事务的永久性。

事务的隔离级别

  • SQL标准的事务隔离级别包括:读未提交(read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(serializable )
  • 读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。
  • 读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。
  • 可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。未提交的更改对其他事务是不可见的
  • 串行化:对应一个记录会加读写锁,出现冲突的时候,后访问的事务必须等前一个事务执行完成才能继续执行。最高的隔离级别

MySQL中的事务

  • MySQL提供了两种事务型的存储引擎: InnoDBNDB Cluster。另外还有一些第三方
    存储引擎也支持事
  • MySQL默认采用自动提交(AUTOCOMIT) 模式。如果不是显式地开始-一个个事务,则每个查询都被当作一事务执行提交操作。在当前连接中,可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交模式:
  • InnoDB采用的是两阶段锁定协议(two-phase locking protocol)。在事务执行过程中,随
    时都可以执行锁定,锁只有在执行COMMIT或者ROLLBACK的时候才会释放,并且所有的
    锁是在同一时刻被释放。
  • InnoDB也支持通过特定的语句进行显式锁定SELECT ... LOCK IN SHARE MODESELECT FOR UPDATE 些语句不属于SQL规范

多版本并发控制MVCC

  • MVCC是行级锁的一个变种,但是它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行。
  • MVCC的实现,是通过保存数据在某个时间点的快照来实现的。也就是说,不管需要执行多长时间,每个事务看到的数据都是一致的。根据事务开始的时间不同,每个事务对同张表,同一时刻看到的数据可能是不一样的。
  • InnoDB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。
  • MVCC只在可重复读和读提交的隔离级别生效。其它两个级别都不兼容

在可重复读(REPEATABLE READ) 隔离级别下,MVCC具体是如何操作的。

SELECT查询操作时

InnoDB会根据以下两个条件检查每行记录:

  • InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
  • 行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前未被删除。

INSERT

  • InnoDB为新播入的每-一行保存当前系统版本号作为行版本号。

DELETE

  • InnoDB为删除的每-*行保存当前系统版本号作为行删除标识。

UPDATE

  • InnoDB为插入-行新记录,保存当前系统版本号作为行版本号,同时保存当前系统
    版本号到原来的行作为行删除标识。

猜你喜欢

转载自blog.csdn.net/u010391342/article/details/89646965