MySQL如果直接使用Select 会怎么样?简单的小项目或者后台管理系统这样的大可忽略,并发量不高,数据量也不大。要是在稍微正式的项目里这么干的话你可能会死的很惨,而大多数码农也会忽略这一点儿。
那会引起什么后果呢?说这个之前先了解下MYSQL的事务隔离级别,官方文档地址如下:
https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html
我来划重点:MYSQL中定义四个事务隔离级别:1992标准: READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ,和 SERIALIZABLE。默认隔离级别InnoDB是 REPEATABLE READ。
可以这么理解:
同一事务中的一致读取,在事务中第一次执行Select读取时建立快照。这就是说你的SELECT在同一事务无论查询多少次最终执行的结果都是一样的。不仅如此,如果同时有Update、Delete和Insert这样的操作它会使用一些锁来保证数据库处理逻辑的正确性,一般范围定义如下,如果是按主键或者索引来取数,那取数过程中只会锁定指定的几条数据,如果是按条件过滤那是按范围锁定数据,至于 Insert的锁可能更复杂和数据结构有关,要问你说这么多锁干嘛?答案是这些锁对我们的Select都有影响,在Select前检查到这样的锁就是等待锁释放。
那重点来了,概括一句就是:在Select A 表,遇到对A表的操作(Update,Delete,Insert)均会阻塞造成等待,而同时使用多个进程Select A的操作之间是相互不影响。
在写的同时读取数据的业务场景还是挺多的,这一部分就是系统不稳定的一个大的隐患。尤其在大的系统搭建中,各自负责自己的业务模块,缺少很好的交流,容易出现这样的问题,最好还是统一要求加上with nolock。
添加的方式也很简单,只需要在事务的开头和结尾加以设置就行了如下:
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
SELECT * FROM TABLE_NAME ;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
如果是自己显工写的事务可以使用以下语句:
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
或者使用全局设置(不推荐)
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED ;
关于锁的更多知识可以参考:https://opensource.actionsky.com/20190331-mysql-insert/
有不同理解可以在公众号给我留言,原创禁止转载。
推荐文章:MySQL 学习笔记系列