Mysql—事务原理与详解

事务的四大特性

如果一个数据库支持事务的操作,那么该数据库必须要具备以下四个特性:

  • 原子性(Atomicity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
  • 持久性(Durability)

其中事务的隔离性是通过MySQL锁机制实现的。原子性,一致性,持久性则是通过MySQL的redo和undo日志记录来完成。

事务启动的两种方式

mysql> create table temp(id int primary key,name varchar(20));
mysql> insert into temp values(1,'a'),(2,'b'),(3,'c');

1、显示启动事务语句,begin或者start transcation。配套的提交语句是commit,回滚语句为rollback。

mysql> begin                                    -- 开启一个事务,start transcation使用情况一样
mysql> update temp set name='cc' where id=3;    -- 修改数据
mysql> rollback;                                -- 回滚事务,这里也可以使用commit提交事务。如果不提交也不回滚,直接退出mysql,则自动回滚。
mysql> select * from temp;                      -- 数据恢复到修改之前的状态了

2、set autocommit=0,这个命令会将这个线程的更新自动提交掉。这意味着如果你只执行一个select语句,这个事务就启动了,并且不会自动提交。这个事务持续存在知道你主动执行commit或rollback语句,或者链接断开。mysql中查看当前自动提交状态的命令为:show VARIABLES like 'autocommit'; 如下value为on代表是自动提交已经打开。

mysql> show variables like 'autocommit';       -- 查看事务自动提交是否开启
mysql> set autocommit=0;                       -- 关闭事务自动提交,值为 1 则是开启事务自动提交
mysql> update temp set name='cc' where id=3;   -- 修改数据
mysql> select * from temp;                     -- 数据修改成功
mysql> rollback;                               -- 回滚事务
mysql> select * from temp;                     -- 数据恢复到修改之前的状态了

事务的隔离级别

1、如果不考虑事务的隔离性的前提下,会发生以下几种问题:

脏读:是指在一个事务处理过程里读取了另一个未提交的事务中的数据。当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。脏数据所指的就是未提交的数据。也就是说,一个事务正在对一条记录做修改,在这个事务完成并提交之前,这条数据是处于待定状态的(可能提交也可能回滚),这时,第二个事务来读取这条没有提交的数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被称为脏读。

不可重复读:是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。即一个事务先后读取同一条记录,而事务在两次读取之间该数据被其它事务所修改,则两次读取的数据不同,我们称之为不可重复读。

幻读 (虚读):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读。是事务非独立执行时发生的一种现象。例如事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

不可重复读和脏读的区别是:脏读是某一事务读取了另一个事务未提交的脏数据,而不可重复读则是读取了前一事务提交的数据。

不可重复读和幻读的区别是:都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

2、MySQL数据库事务的隔离级别有四种,从低到高依次为:

  • Read uncommit (读未提交):最低级别,任何情况都无法保证。
  • Read commit (读已提交):可避免脏读的发生。
  • Repeatable read (可重复读):可避免脏读、不可重复读的发生。
  • Serializable (串行化):可避免脏读、不可重复读、幻读的发生。

这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

以上四种隔离级别最高的是Serializable级别,最低的是Read uncommitted级别,当然级别越高,执行效率就越低。像Serializable这样的级别,就是以锁表的方式(类似于Java多线程中的锁)使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。

在MySQL数据库中,支持上面四种隔离级别,默认的为Repeatable read (可重复读);而在Oracle数据库中,只支持Serializable (串行化)级别和Read committed (读已提交)这两种级别,其中默认的为Read committed级别。

3、在MySQL数据库中查看当前事务的隔离级别:

mysql> select @@tx_isolation;

4、在MySQL数据库中设置当前事务的隔离级别:

mysql> set session transaction isolation level 设置事务隔离级别       -- 设置mysql的隔离级别
mysql> set session transaction isolation level read uncommitted;   -- 设置read uncommitted级别
mysql> set session transaction isolation level read committed;     -- 设置read committed级别
mysql> set session transaction isolation level repeatable read;    -- 设置repeatable read级别
mysql> set session transaction isolation level serializable;       -- 设置serializable级别

mysql> set tx_isolation='read-uncommitted';   /* 设置read uncommitted级别 */
mysql> set tx_isolation='read-committed';     /* 设置read committed级别 */
mysql> set tx_isolation='repeatable-read';    /* 设置repeatable read级别 */
mysql> set tx_isolation='serializable';       /* 设置serializable级别 */

 

https://blog.csdn.net/fg2006/article/details/6937413

https://www.cnblogs.com/fjdingsd/p/5273008.html

https://blog.csdn.net/qq_34569497/article/details/79064208?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param

 

posted @ 2019-09-25 17:53  刘_love_田  阅读(334)  评论(0编辑  收藏  举报