mysql串⾏化有什么⽤_五分钟后,你将真正理解MySQL事务
隔离级别!
什么是事务?
事务是⼀组原⼦性的SQL操作,所有操作必须全部成功完成,如果其中有任何⼀个操作因为崩溃或其他原因⽆法执⾏,那么所有的操作都不会被执⾏。也就是说,事务内的操作,要么全部执⾏成功,要么全部执⾏失败。
事务的结束有两种,当事务中的所有操作全部成功执⾏时,事务提交。如果其中⼀个操作失败,将发⽣回滚操作,撤消之前到事务开始时的所有操作。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
事务的特性
⼀个运⾏良好的事务处理系统,还需要具备四个特性:原⼦性(Atomicity)、⼀致性(Consistency)、隔离性(Isolation)和持续性(Durability)。这四个特性简称为ACID特性。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
原⼦性(Atomicity)
⼀个事务必须被视为⼀个不可分割的最⼩逻辑⼯作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚。对于⼀个事务来说,不可能只执⾏其中的⼀部分操作,⽽不执⾏其中的另外⼀部分操作,这就是事务的原⼦性。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
⼀致性(Consistency)
button是什么意思翻译事务执⾏的结果必须是从⼀个⼀致性的状态转换到另外⼀个⼀致性的状态。当数据库只包含成功事务提交的结果时,就说数据库处于⼀致性状态。如果事务因为崩溃或其他原因尚未完成,被迫中断最终事务没有提交,那么事务中所做的修改也不会保存到数据库中。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
隔离性(Isolation)
通常来说,⼀个事务的执⾏不能其它事务⼲扰。也就是说,⼀个事务内部的操作及使⽤的数据对其它并发事务是隔离的,并发执⾏的各个事务之间不能互相⼲扰。后⾯我们将要讲解隔离级别(Isolation Level)的时候,会发现为什么我们要说“通常来说”是隔离的。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
持续性(Durability)
事务⼀旦提交,它对数据库中的数据的修改就应该是永久性的。此时即使系统崩溃,修改的数据也不会丢失。不过,实际上持久性也分很多不同的级别,有些持久性策略能够提供⾮常强的安全保障,⽽有些则未必。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
事务隔离级别
在SQL标准中定义了四种隔离级别,每⼀种级别都定义了⼀个事务所做的修改,在另外⼀个事务内和事务间,哪些是可见的,哪些是不可见的。低级别的隔离级⼀般⽀持更⾼的并发处理,并拥有更低的系统开销。
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
未提交读(Read Uncommitted)
在未提交读级别中,事务中的修改即使没有提交,对其他事务也是可见的。读取到了事务没有提交的数据,就被成为脏读(Dirty Read)。事务没有提交的数据是很“脏”的,被读取到会引起很多问题。从性能⾓度上看,未提交读级别不会⽐其他级别好很多,但缺乏其他级别的好处,所以在实际应⽤中很少被⽤到。
为加上深对未提交读级别的理解,让我们看⼀个脏读的例⼦,⾸先设置事务隔离级别为未提交读:
mysql> set session transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
再检验⼀下事务隔离级别:
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)
卡网源码左右分别为两个⽤户,左边是⽤户A,右边是⽤户B,时间线从上⾄下:
#⽤户A:查询user表,有⼀条OneMoreStudy的记录
mysql> select * from user;
+----+--------------+
| id | name |
考律师资格证需要什么条件+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#⽤户B:开始事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
#⽤户B:更新user表的⼀条记录
mysql> update user set name = 'OMS' where id = 1;
mysql是什么系统Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#⽤户A:查询user表,有⼀条OMS的记录,脏读
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | OMS |
+----+------+
1 row in set (0.00 sec)
androidmediatype#⽤户B:提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
提交读(Read Committed)
在提交读级别中,⼀个事务开始时,只能查询到其他的事务已经提交的修改。也就是说,⼀个事务从开始到提交之前,任何的修改对其他的事务都是不可见的。提交读级别基本满⾜了事务的隔离性。
不过,在同⼀事务中两次查询之间,有其他事务的修改被提交,那么两次查询到结果可能不相同,这就是不可重复读。
为了更好的理解不可重复读,让我们看⼀个例⼦,⾸先设置事务隔离级别为提交读:
mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
再检验⼀下事务隔离级别:
mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)
左右分别为两个⽤户,左边是⽤户A,右边是⽤户B,时间线从上⾄下:
#⽤户A:开始事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
#⽤户A:查询user表,有⼀条OneMoreStudy的记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#⽤户B:更新user表的⼀条记录
mysql> update user set name = 'OMS' where id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
#⽤户A:查询user表,有⼀条OMS的记录,不可重复读
mysql> select * from user;
+----+------+
| id | name |
+----+------+
| 1 | OMS |
+----+------+
1 row in set (0.00 sec)
#⽤户A:提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
可重复读(Repeatable Read)
在可重复读级别中,保证了在同⼀个事务中多次读取同样记录的结果是⼀致的。即使多次读取之间有其他事务对其结果做了修改,同⼀个事务中多次读取的结果也是⼀致的。可重复读级别也是MySQL的默认事务隔离级别。
不过,当⼀个事务在读过某个范围内的记录时,其他事务⼜在这个范围内插⼊了新的记录,当之前的事务再⼀次读取这个范围的记录时,不会读取到新插⼊的那条记录,这被称为幻读。
为了更好的理解幻读,让我们看⼀个例⼦,⾸先把事务隔离级别设置为可重复读:
mysql> set session transaction isolation level repeatable read;
Query OK, 0 rows affected (0.00 sec)
再检验⼀下事务隔离级别:
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
js图片放大| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
左右分别为两个⽤户,左边是⽤户A,右边是⽤户B,时间线从上⾄下:
#⽤户A:开始事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
#⽤户A:查询user表,有⼀条记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#⽤户B:插⼊⼀条数据
mysql> insert into user (name) value ('OneMoreStudy'); Query OK, 1 row affected (0.01 sec)
#⽤户A:查询user表,还是⼀条记录,幻读
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
+----+--------------+
1 row in set (0.00 sec)
#⽤户A:提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
#⽤户A:查询user表,两条记录
mysql> select * from user;
+----+--------------+
| id | name |
+----+--------------+
| 1 | OneMoreStudy |
| 2 | OneMoreStudy |
+----+--------------+
2 rows in set (0.00 sec)
欢迎关注:万猫学社,每周⼀分享Java技术⼲货。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论