SELECT ... FOR UPDATE or SELECT ... FOR SHARE Locking Reads session
小结:
1、注意使用限制
Locking reads are only possible when autocommit is disabled (either by beginning transaction with START TRANSACTION
or by setting autocommit
to 0.
SELECT ... FOR UPDATE
or SELECT ... FOR SHARE
MySQL :: MySQL 8.0 Reference Manual :: 15.7.2.4 Locking Reads https://dev.mysql.com/doc/refman/8.0/en/innodb-locking-reads.html
15.7.2.4 Locking Reads
If you query data and then insert or update related data within the same transaction, the regular SELECT
statement does not give enough protection. Other transactions can update or delete the same rows you just queried. InnoDB
supports two types of locking reads that offer extra safety:
-
Sets a shared mode lock on any rows that are read. Other sessions can read the rows, but cannot modify them until your transaction commits. If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.
NoteSELECT ... FOR SHARE
is a replacement forSELECT ... LOCK IN SHARE MODE
, butLOCK IN SHARE MODE
remains available for backward compatibility. The statements are equivalent. However,FOR SHARE
supportsOF
,table_name
NOWAIT
, andSKIP LOCKED
options. See Locking Read Concurrency with NOWAIT and SKIP LOCKED.Prior to MySQL 8.0.22,
SELECT ... FOR SHARE
requires theSELECT
privilege and at least one of theDELETE
,LOCK TABLES
, orUPDATE
privileges. As of MySQL 8.0.22, only theSELECT
privilege is required.As of MySQL 8.0.22,
SELECT ... FOR SHARE
statements do not acquire read locks on MySQL grant tables. For more information, see Grant Table Concurrency. -
For index records the search encounters, locks the rows and any associated index entries, the same as if you issued an
UPDATE
statement for those rows. Other transactions are blocked from updating those rows, from doingSELECT ... FOR SHARE
, or from reading the data in certain transaction isolation levels. Consistent reads ignore any locks set on the records that exist in the read view. (Old versions of a record cannot be locked; they are reconstructed by applying undo logs on an in-memory copy of the record.)SELECT ... FOR UPDATE
requires theSELECT
privilege and at least one of theDELETE
,LOCK TABLES
, orUPDATE
privileges.
These clauses are primarily useful when dealing with tree-structured or graph-structured data, either in a single table or split across multiple tables. You traverse edges or tree branches from one place to another, while reserving the right to come back and change any of these “pointer” values.
All locks set by FOR SHARE
and FOR UPDATE
queries are released when the transaction is committed or rolled back.
Locking reads are only possible when autocommit is disabled (either by beginning transaction with START TRANSACTION
or by setting autocommit
to 0.
A locking read clause in an outer statement does not lock the rows of a table in a nested subquery unless a locking read clause is also specified in the subquery. For example, the following statement does not lock rows in table t2
.
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2) FOR UPDATE;
To lock rows in table t2
, add a locking read clause to the subquery:
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
Locking Read Examples
Suppose that you want to insert a new row into a table child
, and make sure that the child row has a parent row in table parent
. Your application code can ensure referential integrity throughout this sequence of operations.
First, use a consistent read to query the table PARENT
and verify that the parent row exists. Can you safely insert the child row to table CHILD
? No, because some other session could delete the parent row in the moment between your SELECT
and your INSERT
, without you being aware of it.
To avoid this potential issue, perform the SELECT
using FOR SHARE
:
SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
After the FOR SHARE
query returns the parent 'Jones'
, you can safely add the child record to the CHILD
table and commit the transaction. Any transaction that tries to acquire an exclusive lock in the applicable row in the PARENT
table waits until you are finished, that is, until the data in all tables is in a consistent state.
For another example, consider an integer counter field in a table CHILD_CODES
, used to assign a unique identifier to each child added to table CHILD
. Do not use either consistent read or a shared mode read to read the present value of the counter, because two users of the database could see the same value for the counter, and a duplicate-key error occurs if two transactions attempt to add rows with the same identifier to the CHILD
table.
Here, FOR SHARE
is not a good solution because if two users read the counter at the same time, at least one of them ends up in deadlock when it attempts to update the counter.
To implement reading and incrementing the counter, first perform a locking read of the counter using FOR UPDATE
, and then increment the counter. For example:
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
A SELECT ... FOR UPDATE
reads the latest available data, setting exclusive locks on each row it reads. Thus, it sets the same locks a searched SQL UPDATE
would set on the rows.
The preceding description is merely an example of how SELECT ... FOR UPDATE
works. In MySQL, the specific task of generating a unique identifier actually can be accomplished using only a single access to the table:
UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();
The SELECT
statement merely retrieves the identifier information (specific to the current connection). It does not access any table.
Locking Read Concurrency with NOWAIT and SKIP LOCKED
If a row is locked by a transaction, a SELECT ... FOR UPDATE
or SELECT ... FOR SHARE
transaction that requests the same locked row must wait until the blocking transaction releases the row lock. This behavior prevents transactions from updating or deleting rows that are queried for updates by other transactions. However, waiting for a row lock to be released is not necessary if you want the query to return immediately when a requested row is locked, or if excluding locked rows from the result set is acceptable.
To avoid waiting for other transactions to release row locks, NOWAIT
and SKIP LOCKED
options may be used with SELECT ... FOR UPDATE
or SELECT ... FOR SHARE
locking read statements.
NOWAIT
A locking read that uses
NOWAIT
never waits to acquire a row lock. The query executes immediately, failing with an error if a requested row is locked.SKIP LOCKED
A locking read that uses
SKIP LOCKED
never waits to acquire a row lock. The query executes immediately, removing locked rows from the result set.NoteQueries that skip locked rows return an inconsistent view of the data.
SKIP LOCKED
is therefore not suitable for general transactional work. However, it may be used to avoid lock contention when multiple sessions access the same queue-like table.
NOWAIT
and SKIP LOCKED
only apply to row-level locks.
Statements that use NOWAIT
or SKIP LOCKED
are unsafe for statement based replication.
The following example demonstrates NOWAIT
and SKIP LOCKED
. Session 1 starts a transaction that takes a row lock on a single record. Session 2 attempts a locking read on the same record using the NOWAIT
option. Because the requested row is locked by Session 1, the locking read returns immediately with an error. In Session 3, the locking read with SKIP LOCKED
returns the requested rows except for the row that is locked by Session 1.
# Session 1:
mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;
mysql> INSERT INTO t (i) VALUES(1),(2),(3);
mysql> START TRANSACTION;
mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE;
+---+
| i |
+---+
| 2 |
+---+
# Session 2:
mysql> START TRANSACTION;
mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT;
ERROR 3572 (HY000): Do not wait for lock.
# Session 3:
mysql> START TRANSACTION;
mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED;
+---+
| i |
+---+
| 1 |
| 3 |
+---+
环境检查
SHOW VARIABLES LIKE '%commit%';
SHOW VARIABLES LIKE '%timeout%';
行锁超时时间
https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_lock_wait_timeout
Property | Value |
---|---|
Command-Line Format | --innodb-lock-wait-timeout=# |
System Variable | innodb_lock_wait_timeout |
Scope | Global, Session |
Dynamic | Yes |
SET_VAR Hint Applies |
No |
Type | Integer |
Default Value | 50 |
Minimum Value | 1 |
Maximum Value | 1073741824 |
The length of time in seconds an InnoDB
transaction waits for a row lock before giving up. The default value is 50 seconds. A transaction that tries to access a row that is locked by another InnoDB
transaction waits at most this many seconds for write access to the row before issuing the following error:
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
When a lock wait timeout occurs, the current statement is rolled back (not the entire transaction). To have the entire transaction roll back, start the server with the --innodb-rollback-on-timeout
option. See also Section 15.21.4, “InnoDB Error Handling”.
You might decrease this value for highly interactive applications or OLTP systems, to display user feedback quickly or put the update into a queue for processing later. You might increase this value for long-running back-end operations, such as a transform step in a data warehouse that waits for other large insert or update operations to finish.
innodb_lock_wait_timeout
applies to InnoDB
row locks. A MySQL table lock does not happen inside InnoDB
and this timeout does not apply to waits for table locks.
The lock wait timeout value does not apply to deadlocks when innodb_deadlock_detect
is enabled (the default) because InnoDB
detects deadlocks immediately and rolls back one of the deadlocked transactions. When innodb_deadlock_detect
is disabled, InnoDB
relies on innodb_lock_wait_timeout
for transaction rollback when a deadlock occurs. See Section 15.7.5.2, “Deadlock Detection and Rollback”.
innodb_lock_wait_timeout
can be set at runtime with the SET GLOBAL
or SET SESSION
statement. Changing the GLOBAL
setting requires privileges sufficient to set global system variables (see Section 5.1.9.1, “System Variable Privileges”) and affects the operation of all clients that subsequently connect. Any client can change the SESSION
setting for innodb_lock_wait_timeout
, which affects only that client.
设置session提交情况
-- SET SESSION autocommit=0;
SHOW VARIABLES LIKE "%commit%";
SET SESSION autocommit=0;
SHOW VARIABLES LIKE "%commit%";
注意 在HeidiSQL工具中,执行一批sql后,再次执行,autocommit值没有变;【需要分析 mysql session 原理】
MySQL :: MySQL 8.0 Reference Manual :: 4.2.2.1 Using Options on the Command Line https://dev.mysql.com/doc/refman/8.0/en/command-line-options.html
For options that take a numeric value, the value can be given with a suffix of K
, M
, or G
to indicate a multiplier of 1024, 10242 or 10243. As of MySQL 8.0.14, a suffix can also be T
, P
, and E
to indicate a multiplier of 10244, 10245 or 10246. Suffix letters can be uppercase or lowercase.
For example, the following command tells mysqladmin to ping the server 1024 times, sleeping 10 seconds between each ping:
mysqladmin --count=1K --sleep=10 ping
For options that take a numeric value, the value can be given with a suffix of K
, M
, or G
to indicate a multiplier of 1024, 10242 or 10243. As of MySQL 8.0.14, a suffix can also be T
, P
, and E
to indicate a multiplier of 10244, 10245 or 10246. Suffix letters can be uppercase or lowercase.
For example, the following command tells mysqladmin to ping the server 1024 times, sleeping 10 seconds between each ping:
mysqladmin --count=1K --sleep=10 ping
SELECT ... FOR UPDATE or SELECT ... FOR SHARE Locking Reads session的更多相关文章
- 浅谈select for update 和select lock in share mode的区别
有些情况下为了保证数据逻辑的一致性,需要对SELECT的操作加锁.InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作. . SELECT …… FOR UP ...
- select for update和select for update wait和select for update nowait的区别
CREATE TABLE "TEST6" ( "ID" ), "NAME" ), "AGE" ,), "SEX ...
- 转 MYSQL SELECT ... FOR UPDATE and SELECT ... LOCK IN SHARE MODE Locking Reads
原文: http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html In some circumstances, a consis ...
- mysql: SELECT ... FOR UPDATE 对SELECT语句的阻塞实验
开两个连接A, B, 分别执行以下三个sql start 和 start ; 在A执行完1和2后, B执行1, 正常B执行2, 立即返回B执行3, 这时候被阻塞了 A执行3后, B的3立即返回 可以得 ...
- Mysql加锁过程详解(4)-select for update/lock in share mode 对事务并发性影响
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- Select for update/lock in share mode 对事务并发性影响
select for update/lock in share mode 对事务并发性影响 事务并发性理解 事务并发性,粗略的理解就是单位时间内能够执行的事务数量,常见的单位是 TPS( transa ...
- lock in share mode 和 select for update
lock in share mode 和 select for update 2018年07月11日 01:57:58 道不虚行只在人 阅读数 146 版权声明:欢迎转载,请注明出处 https ...
- (转载)Select for update/lock in share mode 对事务并发性影响
select for update/lock in share mode 对事务并发性影响 事务并发性理解 事务并发性,粗略的理解就是单位时间内能够执行的事务数量,常见的单位是 TPS( transa ...
- mysql锁SELECT FOR UPDATE【转】
MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认 以MySQL 的InnoDB 为例,预设的Tansaction isolation level 为REPEATABLE ...
随机推荐
- (五)cp命令复制文件或者目录
一.cp的含义.功能及命令格式 cp(英文copy的缩写)命令可以将一个文件或者目录从一个位置复制到另外一个位置.cp的功能就是将一个文件复制成 一个指定的目的文件或者复制到一个指定的目录中,兼具复制 ...
- 10天,从.Net转Java,并找到月薪2W的工作(一)
大学学的是Java,但是工作一直都是.Net方面的工作. 看到各种各样的大厂都是招Java,工资比.Net高,岗位多.而.Net大多都是维护老系统,传统行业这类的工作.甚至发现工作经验不足我一半的薪水 ...
- git pull 和git fetch的区别
git pull 是上下文环境敏感的,它会把所有的提交自动给你合并到当前分支当中,没有复查的过程 而git fetch只是把拉去的提交存储到本地仓库中,真正合并到主分支中需要使用merage head ...
- 三目运算符(C++)
一.简介 固定格式 ?: 三目运算符:可用于赋值语句 三目运算表达式:<表达式1>?<表达式2>:<表达式3> 注:"?"运算符的含义是: 先求 ...
- 一言不合就开始搞JDK源码
Java是一门面向对象的编程语言,那什么是面向对象呢,下面将是历史上最通俗易懂的解释了,请看下图: 哈哈,解释的够清楚的了吧.闪. 从源码学编程的好处 学Java编程时,最好同时看一些Java的源码 ...
- Apache伪静态(Rewrite).htaccess文件详解
Htaccess(超文本访问)是一个简单的配置文件,它允许设计师,开发者和程序员通过它来改变Apache Web服务器的配置.这些功能包括用户重定向.URL重写(url rewrite,国内很多称为伪 ...
- 使用BigDecimal舍小数取整数
项目需求说明: 解决WMS系统收货容差问题,例如:SKU的采购数量95件,容差是5,95+95*5/100=99.75,传WMS的数量是99,且容差传零. 参数说明: 其中ROUND_UP:向上取整, ...
- 【剑指 Offer】06.从尾到头打印链表
题目描述 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回). 示例 1: 输入:head = [1,3,2] 输出:[2,3,1] 限制: 0 <= 链表长度 <= 10 ...
- redis存json数据时选择string还是hash
redis存json数据时选择string还是hash 我们在缓存json数据到redis时经常会面临是选择string类型还是选择hash类型去存储.接下来我从占用空间和IO两方面来分析这两种类型的 ...
- TCP/IP五层模型-传输层-TCP协议
1.定义:TCP是一种面向连接.可靠的.基于字节流的传输控制协议. 2.应用场景:TCP为可靠传输,适合对数据完整性要求高,对延时不敏感的场景,比如邮件. 3.TCP报文:①TCP报文格式: ②TC ...