INNODB_LOCKS 表, 该表由如下字段组成:
lock_id: 锁的 ID.
lock_trx_id: 事务 ID.
lock_mode: 锁的模式.
lock_type: 锁的类型, 表锁还是行锁.
lock_table: 要加锁的表.
lock_index: 锁的索引.
lock_space:InnoDB 存储引擎表空间的 ID 号.
lock_page: 被锁住的页的数量. 若是表锁, 则该值为 NULL.
lock_rec: 被锁住的行的数量. 若是表锁, 则该值为 NULL.
lock_data: 被锁住的行的主键值. 当是表锁时, 该值为 NULL.
通过 select from information_schema.INNODB_LOCK; 可查看
INNODBLOCKWAIT 由 4 个字段组成:
requestingtrxid: 申请锁资源的事务 ID.
requestinglockid: 申请的锁的 ID.
blockingtrxid: 阻塞的锁的 ID.
通过 select from informationschema.INNODBLOCKWAITS; 可查看.
一致性的非锁定读: InnoDB 存储引擎通过行多版本控制的方式来读取当前执行时间数据库中行的数据. 如果读取的行正在执行 Delete,update 操作, 这时读取操作不会因此而会等待行上锁的释放, 相反, InnoDB 存储引擎会去读取行的一个快照数据. 快照数据是指该行之前版本的数据, 该实现是通过 Undo 段来实现. 而 Undo 用来事务中回滚数据, 因此快照本身是没有额外开销的. 此外, 快照数据是不需要上锁的, 因为没有必要对历史的数据进行修改. 一个行可能有不止一个快照数据, 所以称这种技术为行多版本技术. 由此带来并发控制, 称之为多版本并发控制 (Multi VersionConcurrency Control, MVCC).
事务的隔离级别: Read uncommitted,Read committed,Repeatable read,serializable. 在 Read Committed 和 Repeatable Read 下, InnoDB 存储引擎使用非锁定一致性读. 然而, 对于快照的定义却不同. 在 Read Committed 事务隔离级别下, 对于快照数据, 非一致性读总是读取被锁定行的最新一份快照数据. 在 Repeatable 事务隔离级别下, 对于快照数据, 非一致性读总是读取事务开始时的行数据版本.
锁的算法:
Record Lock: 单行记录上的锁
Gap Lock: 间隙锁, 锁定一个范围, 但不包含记录本身
Next-Key Lock:Gap Lock + Record Lock, 锁定一个范围, 并且锁定记录本身. 更加详细的介绍可以参见这篇 blog, http://www.db110.com/?p=1848
锁的问题:
丢失更新: 经典的数据库问题, 当两个或多个事务选择同一行, 然后基于最初选定的值更新该行时, 会发生丢失更新问题. 每个事务都不知道其它事务的存在. 最后的更新将重写由其它事务所做的更新, 这将导致数据丢失.
例:
事务 A 和事务 B 同时修改某行的值,
1. 事务 A 将数值改为 1 并提交
2. 事务 B 将数值改为 2 并提交.
这时数据的值为 2, 事务 A 所做的更新将会丢失.
解决办法: 事务并行变串行操作, 对更新操作加排他锁.
脏读: 一个事务读到另一个事务未提交的更新数据, 即读到脏数据.
例:
1.Mary 的原工资为 1000, 财务人员将 Mary 的工资改为了 8000(但未提交事务)
2.Mary 读取自己的工资 , 发现自己的工资变为了 8000, 欢天喜地!
3. 而财务发现操作有误, 回滚了事务, Mary 的工资又变为了 1000, 像这样, Mary 记取的工资数 8000 是一个脏数据.
解决办法: 脏读只有在事务隔离级别是 Read Uncommitted 的情况下才会出现, innoDB 默认隔离级别是 Repeatable Read, 所以生产环境下不会出现脏读.
不可重复读: 在同一个事务中, 多次读取同一数据, 返回的结果有所不同. 换句话说就是, 后续读取可以读到另一个事务已提交的更新数据. 相反 "可重复读" 在同一事务多次读取数据时, 能够保证所读数据一样, 也就是后续读取不能读到另一事务已提交的更新数据. 脏读和不可重复读的主要区别在于, 脏读是读到未提交的数据, 不可重复读是读到已提交的数据.
例:
1. 在事务 1 中, Mary 读取了自己的工资为 1000, 操作并没有完成
2. 在事务 2 中, 这时财务人员修改了 Mary 的工资为 2000, 并提交了事务.
3. 在事务 1 中, Mary 再次读取自己的工资时, 工资变为了 2000
解决办法: 读到已提交的数据, 一般数据库是可接受的, 因此事务隔离级别一般设为 Read Committed.Mysql InnoDB 通过 Next-Key Lock 算法避免不可重复读, 默认隔离级别为 Repeatable Read.
来源: http://www.bubuko.com/infodetail-2762132.html