mysql笔记(一)

文章目录

  • 1. Mysql架构
    • 1.1 架构图
    • 1.2 读写锁
      • 共享锁:读锁
      • 排他锁:写锁
    • 1.3 锁粒度
      • 表级锁
      • 行级锁
    • 1.4 事务
      • 原子性(atomicity)
      • 一致性(consistency)
      • 隔离性(isolation)
      • 持久性(durability)
    • 1.5 隔离级别
      • READ UNCOMMITTED(未提交读)
      • READ COMMITTED(提交读)
      • REPEATABLE READ(可重复读)
      • SERIALIZABLE(可串行化)
      • 隔离级别图表
    • 1.6 死锁
    • 1.7 事务日志
    • 1.8 MySQL中的事务
      • 自动提交(AUTOCOMMIT)

1. Mysql架构

1.1 架构图

mysql笔记(一)_第1张图片

1.2 读写锁

共享锁:读锁

多个用户同一时刻可以同时读取同一个资源互不干扰

排他锁:写锁

写锁会阻塞其他的写锁和读锁

1.3 锁粒度

表级锁

  1. 开销最小的锁策略
  2. 对整张表加锁

获取表级写锁会阻塞其他用户对该表的所有读写操作,读锁之间是不互相阻塞的

写锁比读锁具有更高的优先级,写锁请求可能会插入到读锁队列前

除储存引擎,Mysql本身也可以使用有效的表锁来实现不同的目的

行级锁

  1. 带来最大的锁开销
  2. 可以最大程度支持并发处理

行级锁只在储存引擎(InnoDB 和 XtraDB)层实现,Mysql服务器层没有实现

1.4 事务

  1. 事务内的语句,要么全部执行成功,要么全部执行失败。支持事务的系统要通过严格的ACID测试。
  2. 对于不需要事务的业务场景,用户可以选择一个非事务型的存储引擎,来获得更高的性能,当然即使存储引擎不支持事务,Mysql服务器的表级锁也可以提供一定程度的保护。

原子性(atomicity)

一个事务必须被视为一个不可分割的最小执行单元,要么全部提交成功,要么全部失败回滚,不能只执行其中的一部分。

一致性(consistency)

数据库总是从一个一致性状态转换到另一个一致性状态,除非事务最终提交,不然事务的修改不会提交到数据库中。

隔离性(isolation)

一个事务在最总提交前,通常对其他事务不可见,如事务a过程中对账号金额200进行了修改,但是事务a还未提交,这时事务b看到的账号金额还是是未修改的200。

持久性(durability)

一旦事务提交,其所做修改会永久保存在数据库中。

1.5 隔离级别

每种存储引擎实现的隔离级别不尽相同

READ UNCOMMITTED(未提交读)

  • 事务中的修改,即使没有提交,对其他事务也都是可见的。
  • 事务可以读取到未提交的数据,这也称为脏读(Dirty Read)。
  • 除非真的有非常必要的理由,在实际应用中一般很少使用。

READ COMMITTED(提交读)

  • 大多数数据库系统的默认隔离级别(Mysql不是0)。
  • 一个事务只能“看见”已经提交的事务所做的修改。一个事务从开始直到提交之前,所做的修改对其他事务不可见。但是可能出现一个事务中两次执行同样查询时,得到结果不一样的情况。
  • 该级别也叫不可重复读(nonrepeatable read)。

不可重复读,例如:

  • 事务A:
select money from user where account = "123";

结果:2000

  • 事务B:
update user set money = 3000 where account = "123";

事务B提交

  • 事务A:
select money from user where account = "123";

结果: 3000
事务A提交

事务A过程中出现了前后查询读取到的数据不一致的问题,所以该级别被称作不可重复读。

REPEATABLE READ(可重复读)

  • 该级别保证了同一事务中多次读取同样记录的结果是一致的。
  • 该级别是Mysql的默认事务级别。但是理论上,该级别还是无法解决另一个幻读(Phantom Read)问题。
  • 幻读(Phantom Read)指某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取某个该范围的记录时,就会产生环行。
  • InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC, Multiversion Concurrency Control)解决幻读问题。

幻读,例如:

  • 事务A:
select * from user;

结果有10行

  • 事务B:
Insert into user value(11,"asd");

事务B提交

  • 事务A:
select * from user;

结果有11行

此时就出现了幻读,两次读取结果行数不一致。

SERIALIZABLE(可串行化)

  • 最高隔离级别。
  • 通过强制事务串行执行避免幻读,简单说就是在读取的每一行数据上都加锁,可能导致大量超市和锁争用的问题。
  • 实际很少使用,除非要非常需要确保数据的一致性而且可以接受没有并发的情况下。

隔离级别图表

mysql笔记(一)_第2张图片

1.6 死锁

当多个事务视图以不同的顺序锁定资源时,就可能会产生死锁。例如,设想下面两个事务同时处理StockPrice表:

事务1:

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 4 and date = '2002-05-01';
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 3 and date = '2002-05-02';
COMMIT;

事务2:

START TRANSACTION;
UPDATE StockPrice SET close = 45.50 WHERE stock_id = 3 and date = '2002-05-01';
UPDATE StockPrice SET close = 19.80 WHERE stock_id = 4 and date = '2002-05-02';

如果凑巧,两个事务都执行了第一条UPDATE语句,同时也锁定了该行数据,接着每个事务都尝试去执行第二条UPDATE语句,却发现该行被锁定了,然后两个事务都等待对方释放锁,同时又持有对方需要的锁,陷入死循环。

  • 为了解决这些问题,数据库系统实现了各种死锁检测和死锁超时机制。
  • InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。

1.7 事务日志

修改数据流程:
修改数据改内存拷贝 -> 修改事务日志 -> 持久化事务日志 -> 内存拷贝持久化

  • 事务日志可以提升事务的效率。
  • 存储引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的事务日志中,而不用每次都将修改的数据本身持久到磁盘上。
  • 事务日志采取追加方式,写日志的操作是在磁盘上的一小块区域进行顺序I/O,不像随机I/O多次移动磁头,所以事务日志效率较高。
  • 事务日志持久以后,内存中被修改的数据在后台可以慢慢地刷回到磁盘。
  • 如果修改已经记录到事务日志并持久化,但是数据本身并没有写回磁盘,此时系统崩溃,存储引擎在重启时可以自动恢复这部分修改的数据。

1.8 MySQL中的事务

MySQL提供了两种事务型的存储引擎:InnoDB和NDB Cluster,另外还有一些第三方的存储引擎也支持事务:XtraDB和PBXT。

自动提交(AUTOCOMMIT)

  • Mysql默认采用自动提交,如果不是显示地开始一个事务,则每个查询都会被当作一个事务执行提交操作。
  • 当前连接中,可以通过设置AUTOCOMMIT变量来启用或者禁用自动提交操作。

你可能感兴趣的:(mysql,mysql)