数据库锁(三)

2019/05/03 数据库

数据库锁(三)

1.事务隔离级别概念

MySql中有四种隔离级别:

  • 读未提交(Read Uncommited):允许一个事务可以看到另一个事务未提交的数据,会产生脏读,不可重复读,幻读;
  • 读已提交(Read Commited):保证一个事务修改的数据提交后才能被另一个事务读取,避免脏读,会产生不可重复读,幻读;
  • 可重复读(Repeatable Read,默认):保证一个事务不能读取另一个事务未提交的事务外,还可以保证避免不可重复读;
  • 串行化(Serializable):事务顺序执行,代价高,最可靠。

存在的三个问题:

  • 脏读:事务1更新了记录,但没用提交,事务2读取该记录,然后事务1回滚,事务2读取无效;
  • 不可重复读:事务1读取一条记录,事务2更新该记录并提交,事务1再次读取,读取到了更新后的值,和第一次读取的值不同;
  • 幻读:事务1读取记录,事务2增加记录并提交,事务1再次读取时看到了事务2新增的记录。

2.MVCC

多版本并发控制技术,是一种乐观锁的实现,通过保存数据在某个时间点的快照来实现。

2.1 Innodb的行结构

Innodb存储的最基本row中额外包含三个字段,DATA_TRX_ID,DATA_ROLL_PTR,DB_ROW_ID。

  • DATA_TRX_ID:6个字节,标记了最近修改(insert update)这条行记录的事务id,即最后一次修改记录的事务id;

    delete操作,在Innodb中也看作是一次update操作,用1个bit表示;

    show engine innodb status 命令查看;

  • DATA_ROLL_PTR:7个字节,是一个指针,指向这条记录的rollback segment(回滚段)的undo log记录;

    update操作的话,记录update前的row值;

  • DB_ROW_ID:6个字节,新行插入而递增,如果表没用设置主键,生成聚簇索引时,适用该值,如果有主键,该值不会出现;

  • DELETE BIT:标识该记录是否被删除,只是标记出来,真正的删除在commit的时候。

行存储结构

2.2 Read-View的结构

每个事务首次执行快照读操作时,会创建一个read_view对象(RR隔离级别中首次执行快照读创建对象,而RC隔离级别中每次执行快照读,都会创建对象),该对象就是用来控制逻辑快照的可见范围的。事务提交后,创建的read_view对象将被销毁。

有三个关键字段用于判断记录的可见范围,分别是trx_ids,low_limit_id,up_limit_id。

  • trx_ids:记录活跃的其他事务的id集合;
  • low_limit_id:trx_ids中最大的事务id+1,即系统中最近一个尚未分配出去的事务id;
  • up_limit_id:trx_ids中最小的事务id。

ct_trx指当前记录的事务id,只有ct_trx<up_limit_id(表示该记录在当前事务开始前已经commit),以及事务id不在trx_ids列表中时,才会返回数据。

RR隔离级别下查询数据

3.总结

  • 设置并查看自动提交,MySQL默认为自动提交(autocommit=1):

    set autocommit = 0;

    SELECT @@autocommit;

  • 设置隔离级别并查看当前隔离级别,MySQL默认为RR隔离级别:

    set session transaction isolation level REPEATABLE read; SELECT @@tx_isolation

  • 查看事务相关的内容:

    SHOW ENGINE INNODB STATUS;

  • read view对象在第一次查询时候产生(RR隔离级别下,RC隔离级别下每次查询都产生新的read view对象);

  • 事务id不是在begin的时候分配的,进行具体的操作时候才会分配,可以通过查询下面的表来监控:

    select * from information_schema.INNODB_TRX;

参考:

Mysql中MVCC的使用及原理详解

关于innodb中MVCC的一些理解

浅析Mysql的隔离级别及MVCC

InnoDB存储引擎MVCC的工作原理

InnoDB MVCC RR隔离级别下的数据可见性总结

Search

    Table of Contents