资讯专栏INFORMATION COLUMN

MySQL系列之-“事务”与“锁”

IT那活儿 / 2457人阅读
MySQL系列之-“事务”与“锁”
点击上方“IT那活儿”,关注后了解更多精彩内容!!!

事务的四大特性

No.1 原子性(Atomicity)

原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须要完全应用到数据库,如果操作失败则不能对数据库有任何影响。

No.2 一致性(Consistency)

一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。
在事务开始和完成时,数据都必须保持一致状态。

No.3 隔离性(Isolation)

数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的 "独立"环境下运行。

No.4 持久性(Durability)

持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
事务完成之后,对于数据的修改是永久的。

并发引发的数据库问题


No.1 数据丢失更新(update lost)

当两个或多个事务选择同一行,最初的事务修改的值,会被后面的事务修改的值覆盖。

No.2 脏读(dirty reads)

当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。

No.3 不可重复读(NonRepeatableReads)

一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现和以前读出的数据不一致。

No.4 幻读(Phantom Reads)

一个事务按照相同的查询条件重新读取以前查询过的数据,却发现其他事务插入了满足其查询条件的新数据

通过事务隔离级别解决事务并发


No.1 未提交读READ-UNCOMMITTED

造成脏读现象,存在脏读、不可重复读、幻读的问题,通过锁解决数据丢失更新的问题。
  • Session 1:

  • Session2:

No.2 读已提交READ-COMMITTED

已提交读隔离级别解决了脏读的问题,但是出现了不可重复读的问题,即事务B在两次查询的数据不一致,解决脏读的问题,存在不可重复读、幻读的问题。
T2时刻无法读到T1时刻未交提的数据,T4时刻能读到T3时刻的数据。

No.3 可重复读(REPEATABLE READ)

mysql 默认级别,解决脏读、不可重复读的问题,存在幻读的问题。使用 MMVC机制实现可重复读。

No.4 串行化(SERIALIZABLE)

mysql中事务隔离级别为serializable时会锁表,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到解决脏读、不可重复读、幻读,可保证事务安全,但完全串行执行,性能最低。

通过锁解决并发事务数据一致性问题


No1. 事务锁策略

1)乐观锁

在关系数据库管理系统里,乐观并发控制(又名“乐观锁”,Optimistic Concurrency Control,缩写“OCC”)是一种并发控制的方法。它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,正在提交的事务会进行回滚。
乐观并发控制相信事务之间的数据竞争(data race)的概率是比较小的,因此尽可能直接做下去,直到提交的时候才去锁定,所以不会产生任何锁和死锁。但如果直接简单这么做,还是有可能会遇到不可预期的结果,例如两个事务都读取了数据库的某一行,经过修改以后写回数据库,这时就遇到了问题。
使用数据版本(Version)记录机制实现,这是乐观锁最常用的一种实现方式。何谓数据版本?即为数据增加一个版本标识,一般是通过为数据库表增加一个数字类型的 “version” 字段来实现。当读取数据时,将version字段的值一同读出,数据每更新一次,对此version值加一。

2)悲观锁

在关系数据库管理系统里,悲观并发控制(又名“悲观锁”,Pessimistic Concurrency Control,缩写“PCC”)是一种并发控制的方法。它可以阻止一个事务以影响其他用户的方式来修改数据。如果一个事务执行的操作都某行数据应用了锁,那只有当这个事务把锁释放,其他事务才能够执行与该锁冲突的操作。
悲观并发控制主要用于数据争用激烈的环境,以及发生并发冲突时使用锁保护数据的成本要低于回滚事务的成本的环境中。
悲观并发控制实际上是“先取锁再访问”的保守策略,为数据处理的安全提供了保证。但是在效率方面,处理加锁的机制会让数据库产生额外的开销,还有增加产生死锁的机会;另外,在只读型事务处理中由于不会产生冲突,也没必要使用锁,这样做只能增加系统负载;还有会降低了并行性,一个事务如果锁定了某行数据,其他事务就必须等待该事务处理完才可以处理那行数。

No2. 锁

1)Myisam引擎锁总结

  • 对MyISAM 表的读操作,不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;

  • 对MyISAM 表的写操作,则会阻塞其他用户对同一表的读和写操作;

简而言之,就是读锁会阻塞写,但是不会阻塞读。而写锁,则既会阻塞读,又会阻塞写
此外,MyISAM 的读写锁调度是写优先,这也是MyISAM不适合做写为主的表的存储引擎的原因。因为写锁后,其他线程不能做任何操作,大量的更新会使查询很难得到锁,从而造成永远阻塞。在mysql中,Myisam引擎开始只支持表锁。
  • 查询表争用情况

2)Innodb引擎锁总结

  • Innodb锁的二种锁定方式:

  1. 共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

  2. 排他锁(X) :SELECT * FROM table_name WHERE ... FOR UPDATE

  • Innodb行锁的演示

  • 无索引表行锁升级为表锁

  • 可重复读的间隙锁以及next-key锁

当我们用范围条件,而不是使用相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据进行加锁;对于键值在条件范围内但并不存在的记录,叫做 "间隙(GAP)" ,InnoDB也会对这个 "间隙" 加锁,这种锁机制就是所谓的间隙锁(Next-Key锁)
mysql> show status like innodb_row_lock%;
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
|
 Innodb_row_lock_current_waits | 0 |
| Innodb_row_lock_time | 24021 |
|
 Innodb_row_lock_time_avg | 6005 |
| Innodb_row_lock_time_max | 6007  |
|
 Innodb_row_lock_waits | 4 |
+-------------------------------+-------+
Innodb_row_lock_current_waits: 当前正在等待锁定的数量
Innodb_row_lock_time: 从系统启动到现在锁定总时间长度
Innodb_row_lock_time_avg:每次等待所花平均时长
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间
Innodb_row_lock_waits: 系统启动后到现在总共等待的次数
当等待的次数很高,而且每次等待的时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手制定优化计划。

3)锁的优化建议

  • 尽可能让所有数据检索都能通过索引来完成,避免无索引行锁升级为表锁。

  • 合理设计索引,尽量缩小锁的范围

  • 尽可能减少索引条件,及索引范围,避免间隙锁

  • 尽量控制事务大小,减少锁定资源量和时间长度

  • 尽可使用低级别事务隔离(但是需要业务层面满足需求)



END


更多精彩干货分享

点击下方名片关注

IT那活儿


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/129730.html

相关文章

  • 关于MySQL的知识点面试常见问题都在这里

    摘要:串行最高的隔离级别,完全服从的隔离级别。但是这将严重影响程序的性能。此外,垂直分区可以简化表的结构,易于维护。 我自己总结的Java学习的一些知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailclimb/Java_Guide 书籍推荐 《高性能MySQL : 第3版》 文字教程推荐 MySQL 教程(菜鸟教程...

    hss01248 评论0 收藏0
  • 关于MySQL的知识点面试常见问题都在这里

    摘要:串行最高的隔离级别,完全服从的隔离级别。但是这将严重影响程序的性能。此外,垂直分区可以简化表的结构,易于维护。 我自己总结的Java学习的一些知识点以及面试问题,目前已经开源,会一直完善下去,欢迎建议和指导欢迎Star: https://github.com/Snailclimb/Java_Guide 书籍推荐 《高性能MySQL : 第3版》 文字教程推荐 MySQL 教程(菜鸟教程...

    newtrek 评论0 收藏0
  • 关于MySQL的知识点面试常见问题都在这里

    摘要:但是这将严重影响程序的性能。垂直分区的优点在于可以使得行数据变小,在查询时减少读取的数,减少次数。此外,垂直分区可以简化表的结构,易于维护。垂直分区的缺点在于主键会出现冗余,需要管理冗余列,并会引起操作,可以通过在应用层进行来解决。 Java面试通关手册(Java学习指南,欢迎Star,会一直完善下去,欢迎建议和指导):https://github.com/Snailclimb/Jav...

    LeoHsiun 评论0 收藏0

发表评论

0条评论

IT那活儿

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<