前言

本文选自网站小册子《My家双雄:深度学习MySQL与MyBatis》:http://www.mybatis.cn/324.html。此书从数据访问存储层为入口,将延伸到分布式、高并发方面的关键技术。希望这本书能对每一个做Java Web开发的读者带来帮助,也欢迎大家提出更多的修改建议。

1、事务

看似简单的一句话:

SELECT 列名称 FROM 表名称

或者

UPDATE 表名称 SET 列名称 = 新值 WHERE 列名称 = 某值

其背后都是有无数条C/C++语句来实现,这一系列对数据进行访问和更新的操作指令,组合成一个整体,从而形成了事务。事务最大的特点:要么全部成功,要么全部失败。

2、SELECT语句在事务中的多种表现

select是个多变的孩子,在不同的应用场景,表现出不一样的行为。虽然select语法非常简单,相信接触sql的人没有不知道的吧。但是将select放在事务中去观察,它的处理规则恐怕很多人都不能完全说清楚吧。下面给大家说一下在事务处理中使用select应该注意的地方:

(1)如果数据库的隔离级别是读已提交(Read Committed),这是很多数据库默认的隔离级别。在这种情况下:

1.1 对于当前事务的更改,即便是前面的修改未提交的,后面的select也是可以看到的。

1.2 除了当前事务之外,select只能看到已提交的事务所做出的更改。往往会出现这种情况:同一个事务的两个相同的select语句,但是执行顺序不同,也可能会返回不同的结果。两个select语句执行间隔的时间里,可能有其他的事务提交,数据被修改了。

(2) 如果数据库的隔离级别是可重复读,事务只能看到它开始前已提交的数据。所以,select既不能看到未提交的数据,也不能看到其所在的事务在执行时被其它事务更新的已提交的数据。

3、UPDATE语句在事务中的表现

上文讲完select,接下来说一下update。闲言少叙,请看下面的正文介绍:

(1)如果数据库的隔离级别是读已提交(Read Committed),这是很多数据库默认的隔离级别。在这种情况下:如果事务要更新一条记录,而这条记录恰好被另一个运行中但未提交事务更改(被锁定或删除),则当前事务会阻塞,等待直到另一个事务提交或回滚后,再继续处理(First Updater Win Rule)。如果另一个事务回滚了,那么当前事务可以继续执行,更新这条记录。如果另一个事务提交了,要分两种情形。第一种:要是这条记录被删除了,那么忽略这条记录;第二种:这条记录被更新了,需要重新判断这条记录是否满足谓词条件(where语句),满足则更新,不满足则忽略这条记录。

(2)如果数据库的隔离级别是可重复读,事务只能看到事务开始前已提交的数据。所以,对于并发的更新操作,与读已提交是类似的。如果事务更新同一条记录,当前事务会阻塞直到另一个并发写的事务结束。如果另一个事务回滚,那么当前事务继续执行,更新这条记录。如果另一个事务提交了,当前事务会回滚,这里的处理与读已提交不同。

4、SQL的输入和输出

任何一条SQL语句都是一个事务,任何一个事务都是有输入和输出的。SQL以记录集合作为操纵对象,所有SQL语句以接受集合作为输入,返回集合作为输出,这种集合特性允许一条SQL语句的输出作为另一条SQL语句的输入,所以SQL语言可以嵌套,这使它具有极大的灵活性和强大的功能。在多数情况下,其他语言需要一大段程序实现的一个单独事件只需要一个SQL语句就可以达到目的,这也意味着用SQL语言可以写出非常复杂的语句。

5、SQL变量

既然SQL有输入输出,那么它也应该有变量来存储。MySQL变量一共分为两大类:用户自定义变量和系统变量。如下:

用户自定义变量包括:局部变量和会话变量。系统变量包括:会话变量和全局变量。

5.1 局部变量

局部变量一般用于SQL的语句块中,比如存储过程中的begin和end语句块。其作用域仅限于该语句块内。生命周期也仅限于该存储过程的调用期间。

drop procedure if exists `add`;
create procedure `add`
(
    in a int,
    in b int
)
begin
    declare c int default 0;
    set c = a + b;
    select c as c;
end;

上述存储过程中定义的变量c就是局部变量。

5.2 会话变量

会话变量即为服务器为每个客户端连接维护的变量。在客户端连接时,使用相应全局变量的当前值对客户端的会话变量进行初始化。设置会话变量不需要特殊权限,但客户端只能更改自己的会话变量,其作用域与生命周期均限于当前客户端连接。如下所示:

SET @num=1;

SELECT @num;

5.3 用户定义变量的步骤

我们可以利用SQL语句将值存储在用户自定义变量中,然后再利用另一条SQL语句来查询用户自定义变量。这样以来,可以再不同的SQL间传递值。


drop table if exists person;
 
CREATE TABLE person (
  ID int,
    NAME VARCHAR ( 20 )
);

insert into person values(1,'tom');

第一步:声明变量,并赋初始值

set @id=0;
set @name='';

第二步:从表中获取数据,并赋值给变量

select ID,NAME INTO @id, @name from person;

第三步:查看变量

select @id;
select @name;

标签: none

添加新评论