绑定完请刷新页面
取消
刷新

分享好友

×
取消 复制
transaction (2)—mysql进阶(五十八)
2023-02-06 09:53:18

上篇文章说了acid四个事务的特性,原子性保证要不两个sql一起执行,要么不执行,隔离性,两个事务之间必须互不干扰,一致性,两边的数据必须保持一致,可以说一致性的前提是原子性和隔离性必须正常,但原子性和隔离性都正常,就能保证一致性吗?并不是,还必须满足其他一些约束,比如金额不能为负数。持久性就是必须持久化到磁盘才算事务成功。

Mysql中事务语法

前面我们重点介绍了理论知识,那么我们在mysql里如何使用呢?

开启事务

我们可以用命令开启事务:

mysql> BEGIN;

Query OK, 0 rows affected (0.00 sec)

mysql> START TRANSACTION;

Query OK, 0 rows affected (0.00 sec)

Begin开启事务或者start transaction开启事务。

不过start transaction 语句后面可以跟随几个修饰符,就是他们几个,

Read only:表示当前事务是只能读取数据,不能修改数据。(如果我们使用create temporary table创建的临时表,由于他们在当前会话可见,所以在只读事务里,也可以对临时表增,删,改)

Read write:表示当前事务是一个读写事务,也可以修改表。

With consistent snapshot :启动一致性读。

//开启一个事务

START TRANSACTION READ ONLY;

//开启多个事务

START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT;

注意:一个事务不能同时设置只读和读写,这样就有冲突了,另外,如果我们没有显式指定开启什么访问模式,那么默认就是读写访问模式。


提交事务

mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)
 
mysql> UPDATE account SET balance = balance - 10 WHERE id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 
mysql> UPDATE account SET balance = balance + 10 WHERE id = 2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

一个完整的事务过程,开启之后,必须commit之后,才会刷新到磁盘。

手动中止事务

如果我们在执行sql的时候,写到一半,发现错了怎么办呢?比如狗给猫转10元,但是写成了转100,这时候我们只要吧上面的commit换成rollback就好。

mysql> ROLLBACK;

Query OK, 0 rows affected (0.00 sec)

值得注意的是,如果在平时开发中,遇到异常,mysql会自动帮我们回滚,这里的回滚是我们自己手动的。

支持事务的存储引擎

我们前面说了,mySIAM是不支持事务的,而支持事务的存储引擎是innoDB,如果开启事务后,mySIAM存储引擎insert into一条数据,然后rollback,这时候 数据不会回滚,查询会查到刚那条数据。但如果是innoDB开启事务后,insert into一条数据,然后rollback,这时候数据会回滚,不会查询到那条数据。

自动提交

Mysql有个系统变量autocommit,

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

这里默认是on,但这个on代表的是每条sql语句有一个独立的事务,这种特性称为事务的自动提交。加入狗给猫转了10元钱,猫加了10元钱,这两个sql语句是在不同的独立事务进行的。

当然如果想关闭这种自动提交,让他们在同一个事务里,可以显式用begin或者start straction启动,或者set autocommit 为off。

这样我们写的sql都在同一个事务里面,直到我们显式commit或者rollback。

隐式提交

前面说过,当我们显式start transaction 和begin ,或者吧系统变量autocommit设置成off,则不会自动提交事务,但如果我们 没有写commit或者rollback,有的语句也会触发提交事务,这些就称为隐式提交。

当我们定义或者修改数据库对象的数据定义语言(DDL):所谓的数据库对象,指的是数据库,表,视图,存储过程等等这些东西,当我们使用create ,alter,drop等语法对这些数据库对象进行操作的时候,就会隐式提交事务。

BEGIN;
SELECT ... # 事务中的一条语句
UPDATE ... # 事务中的一条语句
... # 事务中的其它语句

CREATE TABLE ... # 此语句会隐式的提交前边语句所属于的事务

隐式使用或修改mysql数据库的表

当我们使用alert user,create user,drop user,grant,rename user,revoke,set password等语句也会隐式提交这些内容。

事务控制或关于锁定的语句

当我们事务开没提交,在sql之后,又写了一个start transaction或者begin,会隐式提交前面的sql。

如果吧autocommit 改为on,也会提交事务。

如果有lock tables,unlock tables,也会提交事务。

Mysql复制的语句

使用start slave,stop slave,reset slave,change master to 等语句也会触发提交。

还有很多其他语句也会触发。

保存点

当我们写了一大堆sql,发现其中一个sql写错,然后就rollback,全部恢复,这样总有一夜回到解放前的感觉,怎么解决这个困境呢?

我们可以在sql执行完一段时候,写一个保存点,然后rollback to 保存点。

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
 mysql> update user set uid = '55' where id = '3';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> savepoint s1;
Query OK, 0 rows affected (0.00 sec) 
mysql> update user set uid = '55' where id = '4';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
 mysql> rollback to s1;
Query OK, 0 rows affected (0.00 sec)

大家可以看到,这里就回到了保存点,保存点前面的sql全部都执行了。

RELEASE SAVEPOINT 保存点名称;


文章来源:知乎平台  原文地址:https://zhuanlan.zhihu.com/p/418223375

分享好友

分享这个小栈给你的朋友们,一起进步吧。

MySQL干货资料
创建时间:2020-05-06 14:18:32
每天都有干货输出哦
展开
订阅须知

• 所有用户可根据关注领域订阅专区或所有专区

• 付费订阅:虚拟交易,一经交易不退款;若特殊情况,可3日内客服咨询

• 专区发布评论属默认订阅所评论专区(除付费小栈外)

技术专家

查看更多
  • 飘絮絮絮丶
    专家
戳我,来吐槽~