https://www.cnblogs.com/Katerina/p/11459135.html
数据库事务隔离级别:4 种 (http://www.cnblogs.com/fjdingsd/p/5273008.html)
read uncommitted --> read committed --> repeatable read --> Serializable
脏读 不可重复读 幻读
MySQL的默认隔离级别:Repeatable read。
大多数数据库的默认级别是 Read committed,比如 Sql Server , Oracle。
select @@tx_isolation; -- 查询当前的事务隔离级别
set session transaction isolation level repeatable read; -- 设置当前连接的事务隔离级别(临时更改)
注:
如果要永久更改事务隔离级别,则要在 mysql 的 my.ini 配置中设置
例如:transaction-isolation=Read-Committed
数据库的脏读、不可重复读、幻读以及不可重复读和幻读的区别(http://blog.csdn.net/stu_hsj/article/details/46603681)
脏读:
脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据叫脏读。
例如:事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。
解决办法:把数据库的事务隔离级别调整到READ_COMMITTED
不可重复读:
不可重复读是指在同一个事务内,两个相同的查询返回了不同的结果。
例如:事务T1读取某一数据,事务T2读取并修改了该数据,T1为了对读取值进行检验而再次读取该数据,便得到了不同的结果。 解决办法:把数据库的事务隔离级别调整到REPEATABLE_READ
幻读:
例如:系统管理员A将数据库中所有学生的成绩从具体分数改为ABCDE等级,但是系统管理员B就在这个时候插入了一条具体分数的记录,当系统管理员A改结束后发现还有一条记录没有改过来,就好像发生了幻觉一样。这就叫幻读。
解决办法:把数据库的事务隔离级别调整到SERIALIZABLE_READ
对 REPEATABLE-READ 的测试:(MySQL)
参考:https://www.liaoxuefeng.com/wiki/1177760294764384/1245268672511968
CREATE TABLE `stu` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `age` int(11) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
+----+---------+------+
| id | name | age |
+----+---------+------+
| 1 | zhansan | 25 |
| 2 | lisi | 18 |
+----+---------+------+
开两个 dos 窗口来测试:
REPEATABLE_READ 时,产生幻读测试:(MySQL)
<参考:http://www.cnblogs.com/jack204/archive/2012/06/09/2542940.html>
InnoDB行锁实现方式
InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与Oracle不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!
由于MySQL的行锁是针对索引加的锁,不是针对记录加的锁,所以虽然是访问不同行的记录,但是如果是使用相同的索引键,是会出现锁冲突的。应用设计的时候要注意这一点。
如果出现死锁,可以用SHOW INNODB STATUS命令来确定最后一个死锁产生的原因。
共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。
用SELECT ... IN SHARE MODE获得共享锁,主要用在需要数据依存关系时来确认某行记录是否存在,并确保没有人对这个记录进行UPDATE或者DELETE操作。但是如果当前事务也需要对该记录进行更新操作,则很有可能造成死锁,对于锁定行记录后需要进行更新操作的应用,应该使用SELECT... FOR UPDATE方式获得排他锁。
给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁;
<href:http://stackoverflow.com/questions/4034976/difference-between-read-commit-and-repeatable-read>
read commit 和 repeatable read的比较