mysql有关事务与for update锁之间的爱恨情仇

MySQL基础属性查询

  • 查询事务提交机制
mysql> select @@autocommit ; 
+--------------+
| @@autocommit |
+--------------+
|            0 |
+--------------+
1 row in set (0.00 sec)

0 是手动提交,1是自动提交。

  • 事务隔离级别(默认是可重复读)
mysql> select  @@transaction_isolation ;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ         |
+-------------------------+
1 row in set (0.00 sec)
  • InnoDB锁超时时间
mysql> select  @@innodb_lock_wait_timeout ;
+----------------------------+
| @@innodb_lock_wait_timeout |
+----------------------------+
|                         50 |
+----------------------------+
1 row in set (0.01 sec)

单位:秒

  • 属性模糊搜索
mysql> show  variables   like  '%timeout%' ;
+-----------------------------------+----------+
| Variable_name                     | Value    |
+-----------------------------------+----------+
| connect_timeout                   | 10       |
| delayed_insert_timeout            | 300      |
| have_statement_timeout            | YES      |
| innodb_flush_log_at_timeout       | 1        |
| innodb_lock_wait_timeout          | 1        |
| innodb_rollback_on_timeout        | OFF      |
| interactive_timeout               | 28800    |
| lock_wait_timeout                 | 31536000 |
| mysqlx_connect_timeout            | 30       |
| mysqlx_idle_worker_thread_timeout | 60       |
| mysqlx_interactive_timeout        | 28800    |
| mysqlx_port_open_timeout          | 0        |
| mysqlx_read_timeout               | 30       |
| mysqlx_wait_timeout               | 28800    |
| mysqlx_write_timeout              | 60       |
| net_read_timeout                  | 30       |
| net_write_timeout                 | 60       |
| replica_net_timeout               | 60       |
| rpl_stop_replica_timeout          | 31536000 |
| rpl_stop_slave_timeout            | 31536000 |
| slave_net_timeout                 | 60       |
| ssl_session_cache_timeout         | 300      |
| wait_timeout                      | 28800    |
+-----------------------------------+----------+
23 rows in set (0.00 sec)

对于不确定名字都属性可以进行模糊搜索。

select... for update与事务的纠缠关系

关闭自动事务提交机制 & 事务隔离级别是默认可重复读

t1与t2事务顺序执行,具体流程如下:

  • t1 开启事务并写入数据
mysql> begin ;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into  lock_tbl  values(1,1);
Query OK, 1 row affected (0.01 sec)

mysql> select *  from   lock_tbl ; 
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
+----+------+
1 row in set (0.01 sec)
  • t2开启事务并写入数据
mysql>  begin ;
Query OK, 0 rows affected (0.01 sec)

mysql>  insert into  lock_tbl  values(2,2);
Query OK, 1 row affected (0.01 sec)

mysql> select *  from   lock_tbl ;   
+----+------+
| id | age  |
+----+------+
|  2 |    2 |
+----+------+
1 row in set (0.01 sec)
  • t1提交事务
mysql> commit ; 
Query OK, 0 rows affected (0.02 sec)
  • t2 执行查询语句

mysql> select *  from   lock_tbl ;  
+----+------+
| id | age  |
+----+------+
|  2 |    2 |
+----+------+
1 row in set (0.01 sec)

由于可重复读隔离级别,因此t2无法查询到t1提交insert的数据

  • t2 加锁for update执行查询语句
mysql> select *  from   lock_tbl for  update;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
|  2 |    2 |
+----+------+
2 rows in set (0.01 sec)

此时可以查询到t1事务提交insert的数据

  • t2再次执行非加锁查询
mysql> select *  from   lock_tbl ; 
+----+------+
| id | age  |
+----+------+
|  2 |    2 |
+----+------+
1 row in set (0.01 sec)

此时还是看不到t1提交insert的数据

  • t2事务回滚并查询
mysql> rollback ;  
Query OK, 0 rows affected (0.01 sec)

mysql> select *  from   lock_tbl ;
+----+------+
| id | age  |
+----+------+
|  1 |    1 |
+----+------+
1 row in set (0.01 sec)

此时发现t2事务是回滚了,t2写入数据回滚掉了。但是对于t2 for update是有锁查询虽然可以看到t1写入的数据,但是t2并没有中间提交事务,而是t2加锁的for update可以看到最新数据而已

扩展:将for update写锁换为 for share 结论同for update。

posted @ 2022-12-30 20:44  bf378  阅读(224)  评论(0编辑  收藏  举报