mysql事务(2)-阿里云开发者社区

开发者社区> 沉默王二> 正文

mysql事务(2)

简介: mysql事务
+关注继续查看

从以上步骤可以看出来,使用READ-COMMITTED的时候,一个事务内部,其查询结果会受到其他事务的update和insert影响。



隔离级别为可重复读,测试insert情况

首先我们先看一下命令行模式下,怎么修改事务隔离级别(以下是把可重复读改成提交读,注意如果按照我的测试顺序,请注意修改)

mysql> show variables like 'tx_isolation';

+---------------+-----------------+

| Variable_name | Value           |

+---------------+-----------------+

| tx_isolation  | REPEATABLE-READ |

+---------------+-----------------+

1 row in set


mysql> set global transaction isolation level read committed;

Query OK, 0 rows affected


mysql> show variables like 'tx_isolation';

+---------------+-----------------+

| Variable_name | Value           |

+---------------+-----------------+

| tx_isolation  | REPEATABLE-READ |

+---------------+-----------------+

1 row in set


mysql>

貌似隔离级别没有变?关掉当前命令行,重新打开一个命令行

mysql> show variables like 'tx_isolation';

+---------------+----------------+

| Variable_name | Value          |

+---------------+----------------+

| tx_isolation  | READ-COMMITTED |

+---------------+----------------+

1 row in set


mysql>


事务隔离级别修改完毕后,我们开始测试

事务1 事务2

mysql> show variables like 'tx_isolation';

+---------------+-----------------+

| Variable_name | Value           |

+---------------+-----------------+

| tx_isolation  | REPEATABLE-READ |

+---------------+-----------------+

1 row in set



mysql> start transaction;

Query OK, 0 rows affected



mysql> select * from test;

+----+-------+

| id | value |

+----+-------+

|  1 |     1 |

|  2 |     2 |

|  3 |     3 |

+----+-------+

3 rows in set 1

2 mysql> show variables like 'tx_isolation';

+---------------+-----------------+

| Variable_name | Value           |

+---------------+-----------------+

| tx_isolation  | REPEATABLE-READ |

+---------------+-----------------+

1 row in set



mysql> start transaction;

Query OK, 0 rows affected



mysql> select * from test;

+----+-------+

| id | value |

+----+-------+

|  1 |     1 |

|  2 |     2 |

|  3 |     3 |

+----+-------+

3 rows in set



mysql> insert into test values(4,4);

Query OK, 1 row affected



mysql> select * from test;

+----+-------+

| id | value |

+----+-------+

|  1 |     1 |

|  2 |     2 |

|  3 |     3 |

|  4 |     4 |

+----+-------+

4 rows in set



mysql> select * from test;

+----+-------+

| id | value |

+----+-------+

|  1 |     1 |

|  2 |     2 |

|  3 |     3 |

+----+-------+

3 rows in set 3

4 mysql> commit;

Query OK, 0 rows affected

mysql> select * from test;

+----+-------+

| id | value |

+----+-------+

|  1 |     1 |

|  2 |     2 |

|  3 |     3 |

+----+-------+

3 rows in set



mysql> commit;

Query OK, 0 rows affected 5



从以上结果可以看得出来“该级别保证了同一个事务中,多次读取同样的结果是一致的”。这里并没有出现幻行,因为我的数据库引擎为innodb,书中说这种引擎可以解决幻读的问题。

隔离级别为可重复读,测试update情况

事务1 事务2

mysql> start transaction;

Query OK, 0 rows affected



mysql> select value from test where id=1;

+-------+

| value |

+-------+

|     1 |

+-------+

1 row in set


mysql> start transaction;

Query OK, 0 rows affected



mysql> select value from test where id =1;

+-------+

| value |

+-------+

|     1 |

+-------+

1 row in set



mysql> update test set value=11 where id=1;

Query OK, 1 row affected

Rows matched: 1  Changed: 1  Warnings: 0



mysql> select value from test where id =1;

+-------+

| value |

+-------+

|    11 |

+-------+

1 row in set

mysql> select value from test where id=1;

+-------+

| value |

+-------+

|     1 |

+-------+

1 row in set


mysql> commit;

Query OK, 0 rows affected



mysql> select value from test where id=1;

+-------+

| value |

+-------+

|     1 |

+-------+

1 row in set



mysql> commit;

Query OK, 0 rows affected



update的时候同样符合预期结果。


关于事务日志

关于事务日志的说明中,我们可以看得出来,只要修改的数据已经写入到日志并且持久化了,数据本身还没有写入磁盘时,即使断电了,系统在重启的时候依然会将数据恢复。那么我们再来看看官网给出的innodb_flush_log_at_trx_commit参数的介绍

Controls the balance between strict ACID compliance for commit operations, and higher performance

that is possible when commit-related I/O operations are rearranged and done in batches. You can

achieve better performance by changing the default value, but then you can lose up to a second of

transactions in a crash.

• The default value of 1 is required for full ACID compliance. With this value, the contents of the InnoDB

log buffer are written out to the log file at each transaction commit and the log file is flushed to disk.

• With a value of 0, the contents of the InnoDB log buffer are written to the log file approximately once

per second and the log file is flushed to disk. No writes from the log buffer to the log file are performed

at transaction commit. Once-per-second flushing is not 100% guaranteed to happen every second,

due to process scheduling issues. Because the flush to disk operation only occurs approximately once

per second, you can lose up to a second of transactions with any mysqld process crash.

• With a value of 2, the contents of the InnoDB log buffer are written to the log file after each transaction

commit and the log file is flushed to disk approximately once per second. Once-per-second flushing

is not 100% guaranteed to happen every second, due to process scheduling issues. Because the

flush to disk operation only occurs approximately once per second,

大致的意思是将该属性主要是为数据库的ACID原则进行服务的,并且默认为1,但是实际情况下(我们项目是结合spring和mybatis,可能是某一方面设置不当),设置为2会提高很多的事务性能,从文档中可以看得出来,“1的时候,innodb的缓存会在事务提交或者每秒钟时都会进行磁盘的刷新操作,2的时候,innodb缓存会在提交事务时写入到事务日志但不会刷新磁盘,然后在每秒钟时进行磁盘刷新操作”,2要比1提高很多性能,但是对于隐患来说,我没有太好的理解,按照文档中给出的结果好像是“在操作系统崩溃的时候,2的情况下,会丢失1秒的数据”,但是仔细想想发生的时间节点,1.事务没有commit时,断电了,此时肯定数据是没有更新成功的,因为都还没有来得及写入事务日志,2.事务提交后,在写入事务日志的时候,发生断电,此时无论是参数的值是1还是2,都应该恢复不了数据了,3.每秒钟刷新磁盘时,发生断电,按照《高性能mysql》的字面意思,此时既然事务日志已经持久化了,那么重启后,数据是会自动恢复的。那么疑问来了,2和1的隐患到底在什么情况下会发生。

关于autocommit

mysql默认情况下,该参数是打开的,那么这个参数对于应用了spring和mybatis的项目来说,到底是关闭该参数还是打开该参数,会有怎么样的性能影响,我没有弄清楚,如果有热心的读者可以给出一点答复。

另外我们可以通过以下命令进行该参数的设置,当然1为ON,0为OFF。

mysql> show variables like 'autocommit';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| autocommit    | ON    |

+---------------+-------+

1 row in set


mysql> set autocommit = 0;

Query OK, 0 rows affected


mysql> show variables like 'autocommit';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| autocommit    | OFF   |

+---------------+-------+

1 row in set

————————————————


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
MySQL中事务的分类
MySQL中事务的分类 从事务理论的角度来看,可以把事务分为以下几种类型 扁平事务(Flat Transactions) 带有保存点的扁平事务(Flat Transactions with Savepoints) ...
1303 0
RocketMQ与MYSQL事务消息整合
rocketmq事务消息与mysql事物整合
8515 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
10084 0
MySQL事务的艺术和陷阱
作者在之前的文章 “MySQL事务及为何不能在PHP模仿事务” 里面, 详细说明了事务的优点,并介绍了一些简单的SQL命令,使得应用程序更加健壮。但在web程序员的生命旅程中并没有多少事情是看起来那样简单的。
635 0
彻底搞懂 MySQL 事务的隔离级别
MySQL的事务隔离级别一共有四个,分别是读未提交、读已提交、可重复读以及可串行化。
34592 0
Mysql 事务隔离级别 与 读出现的问题实验
Mysql 事务隔离级别 与 读出现的问题实验 读未提交:一个事务的隔离级别为‘读未提交’,它可以读取其他事务未提交的数据 读已提交:一个事务的隔离级别为‘读已提交’,它只可以读其他事务已提交的数据 可重复读:一个事务的隔离级别为‘可重复读’,不关心其他事务的操作,整个事务内读取的数据一致。
2428 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
13890 0
MySQL的事务隔离级别和锁
MySQL的事务隔离级别:Read Uncommitted【读未提交数据】Read Committed【读已提交数据】Repeatable Read【可重读】Serializable【可串行化】 查看MySQL的事务隔离级别:默认、全局和会话事务隔离级别: SELECT @@tx_isolation SELECT @@global.tx_isolation; SELECT @@ses
3453 0
+关注
沉默王二
微信搜索「沉默王二」,回复关键字「00」获取硬核计算机基础资料。
1084
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载