MySql data operation-connection method, index, transaction, function (2)

1. Introduction to MySQL database connection methods [Cartesian product join, inner join, outer join-left join, outer join-right join]

Cartesian product connection:

SELECT article.id AS id, article.title AS title, article.state as state, article_cate.title as cate 
FROM article,article_cate WHERE article.cate_id = article_cate.id ORDER BY id ; 

Note: order by id refers to ordering based on id after search.

Inner join:

SELECT * FROM lesson  INNER JOIN lesson_student ON lesson.id = lesson_student.lesson_id AND lesson_student.student_id =1


#### from 条件后面的跟的+ 表名称  inner josn + 表名称  on + 查询条件 出来的图就是对应顺序不一致

SELECT * FROM lesson_student INNER JOIN lesson ON lesson.id = lesson_student.lesson_id AND lesson_student.student_id =1

Note: Inner join inner join associated table name on table connection condition ------ sorted by ORDER BY field name id;

Outer join (left join)

SELECT * FROM lesson LEFT JOIN lesson_student ON lesson.id = lesson_student.lesson_id AND lesson_student.student_id =1

Results of the:  

Outer join (right join)

SELECT * FROM lesson RIGHT JOIN lesson_student ON lesson.id = lesson_student.lesson_id AND lesson_student.student_id =1

Results of the: 

Note: When using left and right links, depending on which table is used as the reference object, the data presentation method will be different. See the picture specifically...

2.MySQL index

The establishment of indexes is very important for the efficient operation of mysql. Indexes can greatly improve the retrieval speed of MySQL.

Among them, MySQL’s common index types include ordinary index, unique index, full-text index, and spatial index Sqatial.

Take 500,000 pieces of data as an example to demonstrate the operation:

insert into users(`username`) select username from users

Step 1. Create a database with 500,000 pieces of data;


SET NAMES utf8mb4;
set names utfmb4;设置字符集


## 第一个语句SET NAMES utf8mb4;用于设置会话字符集为utf8mb4。这是为了确保数据的正确存储和检索,特别是对于包含表情符号等特殊字符的文本数据。


SET FOREIGN_KEY_CHECKS = 0;
set foreign_key_checks = 1; 默认值为1,同时表示打开外键约束检查。
 
##第二个语句SET FOREIGN_KEY_CHECKS = 0;用于关闭外键约束检查。在插入或更新数据时,外键约束会检查关联表中是否存在匹配的键。关闭这个检查可以避免在插入或更新数据时引发外键约束错误。注意,在完成插入或更新操作后,应该重新打开外键约束检查,即将SET FOREIGN_KEY_CHECKS设置回默认值1。


Note: These two statements should be executed before executing the table creation statement.

-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `balance` decimal(10, 2) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;


-- ----------------------------
-- Records of user
-- ----------------------------

### collate arrangement rules. For MySQL version 8.0 and above, use the above statement; if it is local before version 8.0, use the following statement to create the table.

-- ----------------------------
-- Table structure for user
-- ----------------------------

DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(0) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
  `balance` decimal(10, 2) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;


-- ----------------------------
-- Records of user
-- ----------------------------

INSERT INTO `user` VALUES (1, '张三', 0.00);
INSERT INTO `user` VALUES (2, '李四', 200.00);
INSERT INTO `user` VALUES (5, 'wangwu', 100.00);

About how to create 500,000 pieces of data;

### The steps on how to insert 500,000 pieces of data are as follows:
(-- Check whether mysql allows creating functions:)
1. SHOW VARIABLES LIKE 'log_bin_trust_function_creators'; 

show variables like 'log_bin_trust_function_createors'

(-- 查看mysql是否允许创建函数:)
1. SHOW VARIABLES LIKE 'log_bin_trust_function_creators'; 


(--Command on: allow creation of functions Settings: (global-valid for all sessions)
2. SET GLOBAL log_bin_trust_function_creators=1;  

set global log_bin_trust_function_creators=1;

(-- 命令开启:允许创建函数设置:(global-所有session都生效)
2. SET GLOBAL log_bin_trust_function_creators=1;  
-- 检查存储过程是否存在
SHOW PROCEDURE STATUS WHERE name = 'insert_user';

-- 如果存在,删除存储过程
DROP PROCEDURE IF EXISTS `insert_user`;

DELIMITER $$
CREATE PROCEDURE  insert_user(START INT, max_num INT)
BEGIN  
	DECLARE i INT DEFAULT 0;   
	#set autocommit =0 把autocommit设置成0  
	SET autocommit = 0;    
	REPEAT  
		SET i = i + 1;  
		INSERT INTO `user` ( id , username, balance ) VALUES ((START+i) ,rand_string(6), rand_num(1,10000));  
		UNTIL i = max_num  
	END REPEAT;  
	COMMIT;  
END$$

-- 插入50万条数据
CALL insert_user(100000,500000); 

Specific details
The following is a detailed interpretation of the code snippet:

```sql
DELIMITER $$
```
The `DELIMITER` statement is used to change the statement delimiter of MySQL, setting it to `$$`. This is to avoid conflicts with semicolons in stored procedures.

```sql
CREATE PROCEDURE insert_emp(START INT, max_num INT)
```
The `CREATE PROCEDURE` statement is used to create a stored procedure named `insert_emp`. It accepts two parameters: `START` and `max_num`, both of integer type.

```sql
BEGIN
```
`BEGIN` marks the beginning of the stored procedure.

```sql
DECLARE i INT DEFAULT 0;
```
The `DECLARE` statement declares a local variable named `i` and initializes it to 0. This variable is used to store a counter for loop iterations.

```sql
SET autocommit = 0;
```
The `SET` statement sets the value of `autocommit` to 0. This disables automatic transaction commit so that the transaction remains open until explicitly committed.

```sql
REPEAT
    SET i = i + 1;
    INSERT INTO `user` (id, username, balance) VALUES ((START + i), rand_string(6), rand_num(1, 10000)); UNTIL
i = max_num END REPEAT;
```
This is a repeated loop block (REPEAT...UNTIL). In each loop, the value of `i` is incremented and the data generated according to the specified rules is inserted into the `user` table. The loop iterates until the value of `i` equals `max_num`.

```sql
COMMIT;
```
The `COMMIT` statement is used to commit the current transaction and persist all previous insert operations to the database.

```sql
END$$
```
`END` marks the end of the stored procedure.

In summary, the function of this stored procedure is to insert an incrementing number starting from `START`, a randomly generated user name and a randomly generated balance into the `user` table until the number of inserted records reaches `max_num`, and then submit affairs. At the same time, to ensure transaction consistency, automatic commit and manual commit transactions are disabled.

Please note that before executing this code, you need to ensure that the `rand_string` and `rand_num` functions exist and that the stored procedure is used correctly in the context of the code.

For other detailed operations, you can view the documentation and conduct experiments by yourself.

3. Mysql transaction:

Transaction processing can be used to maintain the integrity of the database and ensure that batches of SQL statements are either all executed or not.
implement.

1.Create the user table as a demonstration

## 由于版本不一样创建数据库执行语句有一点差异化:
## collate =  utf8mb4_0900_ai_ci 可能需要改成:utf8mb4_general_ci
## 也就是说排序规则改成 utf8mb4_general_ci 是因为本地的navicat for mysql 工具导致的
## 作者本地使用的工具是 v11.0.10 -企业版本


SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ---------------------------- 
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(0) NOT NULL AUTO_INCREMENT, 
`username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL
DEFAULT NULL, 
`balance` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;


-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '熊大', 100.00);
INSERT INTO `user` VALUES (2, '光头强', 100.00);
SET FOREIGN_KEY_CHECKS = 1;


---------------------------------分界线-------------------------------------------

## 高级版本执行以下语句
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for user
-- ---------------------------- 
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(0) NOT NULL AUTO_INCREMENT, `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL
DEFAULT NULL, `balance` decimal(10, 2) NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;


-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES (1, '熊大', 100.00);
INSERT INTO `user` VALUES (2, '光头强', 100.00);
SET FOREIGN_KEY_CHECKS = 1;

2. Case: Xiong Da’s account transferred 100 yuan to Bald Qiang’s account

How to implement the idea:
1. 100 yuan is deducted from Xiong Da ’s account
UPDATE user set balance = balance-100 WHERE id=1
2. Bald Qiang ’s account increased by 100 yuan
UPDATE user set balance = balance+100 WHERE id=2
Method execution:
UPDATE user set balance = balance-100 WHERE id=1

UPDATE user set balance = balance+100 WHERE id=2



反馈结果:

[Err] 1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE user set balance = balance+100 WHERE id=2' at line 3
Feedback results and problem analysis:
1. If the SQL statement update data is executed in a single sentence, it is definitely feasible and there is no obvious error message;
2. Use two sql sentences to update other attribute values ​​​​under different id values ​​in the update. At this time, the feedback result is the mysql syntax error of err and tells you where the error point is.
If after we update Xiong Da ’s account, an error occurs when preparing to update Bald Qiang’s account (such as a program error, or the database does not exist)
error such as incorrect connection or abnormal power outage). This will lead to data inconsistency. In order to ensure data consistency, at this time
We can use transactions.

3. Introduce the concept of using transactions, or the timing of using transactions

 Main concepts of transactions:

        BEGIN (begin) starts a transaction

        ROLLBACK (rollback) transaction rollback

        COMMIT (commit) transaction confirmation

Actual usage time:
  

Introducing in-depth thinking on the previous question
1. Xiong Da’s account decreases by 100
2. Bald Qiang’s account increases by 100

So is the use of relative transactions like this:


begin;

update user set balance = balance-100 where id=1;

rollback; 只有执行报错时候才可以使用 回滚操作;



The above is a demonstration case of the timing of using rollback to roll back the transaction at that time.
Attached is the corresponding code:
begin;
update user set balance = balance-100 where id=1;
update user set balance = balance+100 where id=2;
commit;

The above are the corresponding matters,

4. mysql lock

The locks in Mysql include table-level locks and row-level locks;
The most commonly used table-level locks

1. Add read lock

The so-called read lock can be read concurrently, but cannot be written concurrently. During the read lock period, no write operation can be performed until the lock is released;
scenes to be used:
        Read the latest version of the result set while preventing other transactions from updating the result set
It is mainly used to confirm whether a certain row of records exists when data dependencies are required, and to ensure that no one performs operations on this record.
UPDATE or DELETE operation
Add a read lock to table user: lock table user read;
Unlock user's read lock: unlock tables;

2. Add write lock

Only users who lock the table can perform read and write operations, other users cannot (concurrent operations on product inventory)
scenes to be used:
lock table user write;
unlock tables;
Use read-write locks according to actual business needs. The above is a simple operation of table-level locks.

Replenish:

Row-level locking: Each operation locks the corresponding row data.

Row-level locking locks the corresponding row data for each operation. The locking granularity is the smallest, the probability of lock conflicts is the lowest, and the concurrency is the highest. Applied in InnoDB storage engine.

InnoDB data is organized based on indexes, and row locks are implemented by locking index entries on the index, rather than locking records . For row-level locks, they are mainly divided into the following three categories:

  1. Row lock (Record Lock): Locks a single row record to prevent other transactions from updating and deleting the row. Supported under both RC and RR isolation levels.
  2. Gap Lock : Locks the gap between index records (excluding this record) to ensure that the gap between index records remains unchanged and prevents other transactions from inserting in this gap and causing phantom reads. Supported under R isolation level.
  3. Next- Key Lock : A combination of row lock and gap lock, locking the data at the same time and locking the gap in front of the data . Supported under RR isolation level.

InnoDB implements the following two types of row locks:

  • Shared lock (S): allows one transaction to read a row and prevents other transactions from obtaining an exclusive lock on the same data set.
  • Exclusive lock (X): Allows transactions that obtain exclusive locks to update data, and prevents other transactions from obtaining shared locks and exclusive locks on the same data set. male

In row locks, shared locks and shared locks are not mutually exclusive, shared locks and exclusive locks are mutually exclusive; exclusive locks and exclusive locks are mutually exclusive.

In the InnoDB engine, row locks are added when executing SQL:

SQL row lock type illustrate
INSERT ... exclusive lock Automatically lock
UPDATE ... exclusive lock Automatically lock
DELETE ... exclusive lock Automatically lock
SELECT (normal) without any lock
SELECT ... LOCK IN SHARE MODE shared lock Need to manually add LOCK IN SHARE MODE after SELECT
SELECT ...FOR UPDATE exclusive lock You need to manually add FOR UPDATE after SELECT

By default, InnoDB runs at the REPEATABLE READ (RR) transaction isolation level, and InnoDB uses next-key (next-key) locks for searches and index scans to prevent phantom reads.

  • When retrieving against a unique index, equivalent matching of existing records will be automatically optimized for row locking.
  • InnoDB's row lock is a lock added to the index . If data is not retrieved through index conditions, InnoDB will lock all records in the table, and it will be upgraded to a table lock .

Instructions on Gap Lock Pro Key Lock ( to prevent phantom reading ):

  1. Equivalent queries on indexes (unique indexes) are optimized to gap locks when locking non-existent records.
  2. For equivalent queries on indexes (ordinary indexes), when the last value does not meet the query requirements when traversing to the right, the next-key lock degenerates into a gap lock.
  3. Range query on index (unique index) - will access until the first value that does not meet the condition.

Specific instructions:

 -- 首先,准备一张表,id为主键,id分别为 1,3,10,15
 mysql> select * from user_innodb;
 +----+----------+------+
 | id | username | age  |
 +----+----------+------+
 |  1 | 张三     |    1 |
 |  3 | 李四     |    4 |
 | 10 | 王五     |    9 |
 | 15 | 赵六     |   15 |
 +----+----------+------+
 4 rows in set (0.00 sec)
 ​
 ​
 -- 对于1、索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。
 ​
 -- 说明,当开启事务后,如果 此时执行 下面update语句
 update user_innodb set username = '王五' where id = 7
 -- 因为不存在 id = 7 的数据,这是就会给 id = 2 到 id = 9(不包含 4和 10)之间加间隙锁,此时其他客户端想insert (或 update 或 delete)id在2到9之间的数据就会进入阻塞状态。
 ​
 ​
 ​
 -- 对于2、索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock退化为间隙锁。
 -- 首先创建一个 非唯一的普通索引 比如 age
 mysql> create index idx_user_age on user_innodb(age);
 Query OK, 0 rows affected (0.09 sec)
 Records: 0  Duplicates: 0  Warnings: 0
 ​
 -- 查看索引
 mysql> show index from user_innodb;
 +-------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
 | Table       | Non_unique | Key_name     | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment | Visible |
 +-------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
 | user_innodb |          0 | PRIMARY      |            1 | id          | A         |           3 |     NULL |   NULL |      | BTREE      |         |               | YES     |
 | user_innodb |          1 | idx_user_age |            1 | age         | A         |           4 |     NULL |   NULL | YES  | BTREE      |         |               | YES     |
 +-------------+------------+--------------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+---------+
 2 rows in set (0.09 sec)
 ​
 -- 首先开启事务
 -- 当执行下列语句时,若执行的是 select * from user_innodb where age = 4; 不会加锁
 select * from user_innodb where age = 4 lock in share mode; 
 ​
 ​
 -- 查看锁的情况,与表锁中查看意向锁的SQL一致
 mysql> select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
 mysql> select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
 +---------------+-------------+--------------+-----------+-----------+-----------+
 | object_schema | object_name | index_name   | lock_type | lock_mode | lock_data |
 +---------------+-------------+--------------+-----------+-----------+-----------+
 | heima_learn   | user_innodb | NULL         | TABLE     | IS        | NULL      |
 | heima_learn   | user_innodb | idx_user_age | RECORD    | S         | 4, 3      |
 | heima_learn   | user_innodb | PRIMARY      | RECORD    | S         | 3         |
 | heima_learn   | user_innodb | idx_user_age | RECORD    | S,GAP     | 9, 10     |
 +---------------+-------------+--------------+-----------+-----------+-----------+
 ​
 -- 因为 age 是一个普通索引,可能会出现重复的数据,所以说此时会加 3 个共享锁
 -- 第一个  | S         | 4, 3      | 
 -- 这个index_name =idx_user_age,lock_mode中没有GAP  (这里的 4, 3 指的是主键 age 的值为 4,id的值为 3) 的临键锁,表示数据 id = 3 的临键锁,值id = 2,3
 ​
 ​
 -- 第二个 | S         | 3         | 
 -- 第二个的 index_name 为 PRIMARY,表示 给id = 3 (age = 4)的数据加了行锁
 ​
 -- 第三个 | S,GAP     | 9, 10     | 
 -- 这里(9 代表 age = 9, 10 代表 id = 10) index_name = idx_user_age,在 lock_mode 存在 GAP,表示是一个间隙锁,锁住的数据为 id = 4 到 id = 9。
 ​
 -- 这么做的操作就是为了防止出现 幻读
 ​
 ​
 ​
 ​
 -- 对于3、索引上的范围查询(唯一索引)--会访问到不满足条件的第一个值为止。
 ​
 -- 重新开启事务
 -- 执行下列语句
  select * from user_innodb where id >= 10 lock in share mode;
  
  -- 查看锁的情况
 mysql> select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
 +---------------+-------------+------------+-----------+-----------+------------------------+
 | object_schema | object_name | index_name | lock_type | lock_mode | lock_data              |
 +---------------+-------------+------------+-----------+-----------+------------------------+
 | heima_learn   | user_innodb | NULL       | TABLE     | IS        | NULL                   |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | 10                     |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | supremum pseudo-record |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | 15                     |
 +---------------+-------------+------------+-----------+-----------+------------------------+
 4 rows in set (0.00 sec)
 ​
 -- 可以看出加了,id = 10的行锁,id = 15及id > 10 到 id = 15的临键锁,id = 15 及id > 15 的临键锁
 ​
 ​
 -- 当继续执行下面SQL时 
 select * from user_innodb where id >= 9 lock in share mode;
 ​
  
  -- 查看锁的情况
 mysql> select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;
 +---------------+-------------+------------+-----------+-----------+------------------------+
 | object_schema | object_name | index_name | lock_type | lock_mode | lock_data              |
 +---------------+-------------+------------+-----------+-----------+------------------------+
 | heima_learn   | user_innodb | NULL       | TABLE     | IS        | NULL                   |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | 10                     |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | supremum pseudo-record |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | 10                     |
 | heima_learn   | user_innodb | PRIMARY    | RECORD    | S         | 15                     |
 +---------------+-------------+------------+-----------+-----------+------------------------+
 --可以看出,此时的锁的情况是 id = 10的行锁,id = 10 到 id > 10 的临键锁,id = 15 的行锁
I hope my notes will be helpful to you in your study! come on!
Citing article address:

Guess you like

Origin blog.csdn.net/A_LWIEUI_Learn/article/details/132271727