关于MySQL中SELECT语句的原子性问题

在MySQL数据库中存在一张settings表:

snamesvalue
no0
no20

同时存在以下两个函数:

CREATE FUNCTION `fn_inc_no`() RETURNS int(11)
BEGIN
    DECLARE val INT DEFAULT 0;
    
    UPDATE settings
    SET svalue = svalue + 1
    WHERE sname = 'no';
    
    SELECT svalue INTO val FROM settings WHERE sname = 'no';
    
    RETURN val;
END

CREATE FUNCTION `fn_inc_no2`() RETURNS int(11)
BEGIN
    DECLARE val INT DEFAULT 0;
    
    UPDATE settings
    SET svalue = svalue + 1
    WHERE sname = 'no2';
    
    SELECT svalue INTO val FROM settings WHERE sname = 'no2';
    
    RETURN val;
END

如果此时在Java程序中运行如下代码:

Statement query = conn.createStatement();
ResultSet rs = query.executeQuery("SELECT fn_inc_no() AS no, fn_inc_no2() AS no2");

在多个线程(测试时使用了10个线程)中多次(测试时重复执行10000次)执行以上代码,最后得到的 no 和 no2 总是相等的。这是否说明了这条SELECT语句当中的fn_inc_no和fn_inc_no2总是在同一个事务中执行的,是否说明此条SELECT语句在MySQL中本身是一个原子操作?

不同的函数操作的两个不同行,说明不了任何问题。
前条语句更新,后条语句查询,肯定返回的是更新后的结果。

也不用多个线程循环,你让两个函数操作同一行记录, 第一赋值为3,第二个不赋值,直接查询,看看能不能查询出3即可。

不同的函数调用是在不同的事务中。

本来就是2行,你分别更新,分别查询相同的次数, 结果集肯定一样啊?凭啥不一样。

在mysql数据库中创建了settings和settings两张表:
settings:

snamesvalue
no0

settings2:

snamesvalue
no0

同时有两个函数分别对这两张表进行修改:

DELIMITER $$
CREATE FUNCTION `fn_inc_no`() RETURNS int
    DETERMINISTIC
BEGIN
    DECLARE val INT(11) DEFAULT 0;
    
    UPDATE settings
    SET svalue = svalue + 1
    WHERE sname = 'no';

    SELECT svalue INTO val
    FROM settings
    WHERE sname='no';
    
    RETURN val;
END$$
DELIMITER ;
DELIMITER $$
CREATE FUNCTION `fn_inc_no2`() RETURNS int
    DETERMINISTIC
BEGIN
    DECLARE val INT(11) DEFAULT 0;
    
    UPDATE settings2
    SET svalue = svalue + 1
    WHERE sname = 'no';

    SELECT svalue INTO val
    FROM settings2
    WHERE sname='no';
    
    RETURN val;
END$$
DELIMITER ;

执行以下语句:

SELECT fn_inc_no() AS no1, fn_inc_no2() AS no2;

然后执行

-- 需要开启binlog
-- <binlog>替换为binlog文件名,<pos>替换为binlog文件中的起始位置
SHOW BINLOG EVENTS IN '<binlog>' FROM <pos>

可以发现fn_inc_no和fn_inc_no2是在相同的事务中执行的:

| Log_name          | Pos       | Event_type           | Server_id | End_log_pos | Info                                                              |
| ----------------- | --------- | -------------------- | --------- | ----------- | ----------------------------------------------------------------- |
| mysql-bin.000055  | 916835895 | Anonymous_Gtid       | 133026001 | 916835974   | SET @@SESSION.GTID_NEXT= 'ANONYMOUS'                              |
| mysql-bin.000055    | 916835974 | Query                | 133026001 | 916836058   | BEGIN                                                             |
| mysql-bin.000055    | 916836058 | Table_map            | 133026001 | 916836119   | table_id: 3885 (test.settings)                                    |
| mysql-bin.000055    | 916836119 | Table_map            | 133026001 | 916836181   | table_id: 3887 (test.settings2)                                   |
| mysql-bin.000055    | 916836181 | Update_rows          | 133026001 | 916836231   | table_id: 3885                                                    |
| mysql-bin.000055    | 916836231 | Update_rows          | 133026001 | 916836279   | table_id: 3887 flags: STMT_END_F                                  |
| mysql-bin.000055    | 916836279 | Xid                  | 133026001 | 916836310   | COMMIT /* xid=92321411 */                                         |