資料庫系統原理之資料庫安全與保護

来源:https://www.cnblogs.com/QiaoPengjun/archive/2023/04/01/17279396.html
-Advertisement-
Play Games

資料庫安全與保護 第一節 資料庫完整性 資料庫完整性是指資料庫中數據的正確性和相容性。 數據完整性約束是為了防止資料庫中存在不符合語義的數據,為了維護數據的完整性,DBMS 必須提供一種機制來檢查資料庫中的數據,以判斷其是否滿足語義規定的條件。 這些加在資料庫數據之上的語義約束條件就是數據完整性約束 ...


資料庫安全與保護

第一節 資料庫完整性

  • 資料庫完整性是指資料庫中數據的正確性和相容性。
  • 數據完整性約束是為了防止資料庫中存在不符合語義的數據,為了維護數據的完整性,DBMS 必須提供一種機制來檢查資料庫中的數據,以判斷其是否滿足語義規定的條件。
  • 這些加在資料庫數據之上的語義約束條件就是數據完整性約束。
  • DBMS 檢查數據是否滿足完整性約束條件的機制就稱為完整性檢查。

一、完整性約束條件的作用對象

  • 完整性約束條件是完整性控制機制的核心。
  • 完整性約束條件的作用對象可以是列、元組和表。

(1)列級約束

列級約束主要指對列的類型、取值範圍、精度等的約束,具體包括如下內容:

  • 對數據類型的約束,其包括數據類型、長度、精度等。
  • 對數據格式的約束。
  • 對取值範圍或取值集合的約束。
  • 對空值的約束。

(2)元組約束

元組約束指元組中各個欄位之間的相互約束。

(3)表級約束

表級約束指若幹元組之間、關係之間的聯繫的約束。

二、定義與實現完整性約束

1 實體完整性

在MySQL中,實體完整性是通過主鍵約束和候選鍵約束來實現的。

(1)主鍵約束

主鍵可以是表中的某一列,也可以是表中多個列所構成的一個組合。

其中,由多個列組合而成的主鍵也稱為複合主鍵。

在MySQL中,主鍵列必須遵守如下一些規則:

  • 每一個表只能定義一個主鍵。
  • 主鍵的值,也稱為鍵值,必須能夠唯一標誌表中的每一行記錄,且不能為NULL。也就是說,表中兩個不同的行在主鍵上不能具有相同的值。這是唯一性原則。
  • 複合主鍵不能包含不必要的多餘列。也就是說,當從一個複合主鍵中刪除一列後,如果剩下的列構成主鍵仍能滿足唯一性原則,那麼這個複合主鍵是不正確的。這是最小化原則。
  • 一個列名在複合主鍵的列表中只能出現一次。

主鍵約束可以在 CREATE TABLE 或 ALTER TABLE 語句中使用關鍵字“PRIMARY KEY”來實現。

其方式有兩種:

  • 一種是作為列的完整性約束,此時只需在表中某個列的屬性定義後加上關鍵字 “PRIMART KEY” 即可。
  • 一種是作為表的完整性約束,需要再表中所有列的屬性定義後添加一條 PRIMARY KEY(index_col_name, ...) 格式的子句。

註意:

如果主鍵僅由一個表中的某一列所構成,上述兩種方法均可以定義主鍵約束。

如果主鍵是由表中多個列所構成的一個組合,則只能用上述第二種方法定義主鍵約束。

定義主鍵約束後,MySQL 會自動為主鍵創建一個唯一性索引,用於在查詢中使用主鍵對數據進行快速檢索,該索引名預設為 PRIMARY,也可以重新自定義命名。

(2)候選鍵約束

任何時候,候選鍵的值必須是唯一的,且不能為 NULL。

候選鍵可以在 CREATE TABLE 或 ALTER TABLE 語句中使用關鍵字“UNIQUE”來定義,其實現方法與主鍵約束相似,同樣可作為列或者表(關係)的完整性約束兩種方式。

MySQL中候選鍵與主鍵之間存在以下幾點區別:

  • 一個表中只能創建一個主鍵,但可以定義若幹個候選鍵。
  • 定義主鍵約束時,系統會自動產生 PRIMARY KEY 索引,而定義候選鍵約束時,系統會自動產生 UNIQUE 索引。

2 參照完整性

外鍵聲明的方式:

  • 在表中某個列的屬性定義後直接加上”reference_definition“語法項。
  • 在表中所有列的屬性定義後添加”FOREIGN KEY (index_col_name, ...) reference_definition“ 子句的語法項。

"reference_definition" 語法項的定義:

REFERENCES tbl_name (index_col_name, ...)
	[ON DELETE reference_option]
	[ON UPDATE reference_option]

index_col_name 的語法格式:

col_name [(length)] [ASC | DESC]

reference_option 的語法格式:

RESTRICT | CASCADE | SET NULL | NO ACTION

限制策略    級聯策略    置空策略    不採取實施策略

例子:在資料庫 mysql_test 中創建一個商品訂單表 orders,該表包含的訂單信息有:訂單號 oder_id、訂購商品名 order_product、訂購商品類型 order_product_type、訂購客戶 id 號 cust_id、訂購時間 order_date、訂購價格 order_price、訂購數量 order_amount。要求商品訂單表 orders 中的所有訂購客戶信息均已在表 customers 中記錄在冊。

mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> create table orders
    -> (
    -> order_id int not null auto_increment,
    -> order_product char(50) not null,
    -> order_product_type char(50) not null,
    -> cust_id int not null,
    -> order_date datetime not null,
    -> order_price double not null,
    -> order_amount int not null,
    -> primart key (order_id),
    -> foreign key (cust_id)
    -> references customers(cust_id)
    -> on delete restrict
    -> on update restrict
    -> );
ERROR 1064 (42000): 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 'key (order_id),
foreign key (cust_id)
references customers(cust_id)
on delete r' at line 10
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field        | Type     | Null | Key | Default | Extra          |
+--------------+----------+------+-----+---------+----------------+
| cust_id      | int      | NO   | PRI | NULL    | auto_increment |
| cust_name    | char(20) | YES  |     | NULL    |                |
| cust_sex     | char(1)  | YES  |     | M       |                |
| cust_city    | char(10) | NO   |     | Beijing |                |
| cust_address | char(50) | YES  |     | NULL    |                |
| cust_contact | char(50) | YES  |     | NULL    |                |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)

mysql> create table orders ( order_id int not null auto_increment, order_product char(50) not null, order_product_type char(50) not null, cust_id int not null, order_date datetime not null, order_price double not null, order_amount int not null, primary key (order_id), foreign key (cust_id)  references customers(cust_id) on delete restrict on update restrict );
Query OK, 0 rows affected (0.05 sec)

mysql> desc orders;
+--------------------+----------+------+-----+---------+----------------+
| Field              | Type     | Null | Key | Default | Extra          |
+--------------------+----------+------+-----+---------+----------------+
| order_id           | int      | NO   | PRI | NULL    | auto_increment |
| order_product      | char(50) | NO   |     | NULL    |                |
| order_product_type | char(50) | NO   |     | NULL    |                |
| cust_id            | int      | NO   | MUL | NULL    |                |
| order_date         | datetime | NO   |     | NULL    |                |
| order_price        | double   | NO   |     | NULL    |                |
| order_amount       | int      | NO   |     | NULL    |                |
+--------------------+----------+------+-----+---------+----------------+
7 rows in set (0.00 sec)

mysql>

當指定一個外鍵時,需要遵守下列原則:

  • 被參照表必須已經用一條 CREATE TABLE 語句創建了,或者必須是當前正在創建的表。
    • 如若是後一種情形,則被參照表與參照表是同一個表,這樣的表稱為自參照表(self-referencing table),這種結構稱為自參照完整性(self-referential integrity)。
  • 必須為被參照表定義主鍵。
  • 必須在被參照表的表名後面指定列名或列名的組合。
    • 這個列或列組合必須是這個被參照表的主鍵或候選鍵。
  • 儘管主鍵是不能夠包含空值的,但允許在外鍵中出現一個空值。
    • 這意味著,只要外鍵的每個非空值出現在指定的主鍵中,這個外鍵的內容就是正確的。
  • 外鍵中的列的數目必須和被參照表的主鍵中的列的數目相同。
  • 外鍵中的列的數據類型必須和被參照表的主鍵中的對應列的數據類型相同。

3 用戶定義的完整性

  • 非空約束
    • NOT NULL
  • CHECK 約束
    • CHECK (expr)
    • 基於列的 CHECK 約束
    • 基於表的 CHECK 約束
  • 觸發器

三、命名完整性約束

CONSTRAINT [symbol]
  • 只能給基於表的完整性約束指定名字,而無法給基於列的完整性約束指定名字

四、更新完整性約束

添加約束:ALTER TABLE 語句中使用 ADD CONSTRAINT子句

  • 完整性約束不能直接被修改。
    • 若要修改某個約束,實際上是用 ALTER TABLE 語句先刪除該約束,然後再增加一個與該約束同名的新約束
  • 使用 ALTER TABLE 語句,可以獨立地刪除完整性約束,而不會刪除表本身。
    • 若使用 DROP TABLE 語句刪除一個表,則表中所有的完整性約束都會自動被刪除。

第二節 觸發器

觸發器(Trigger)是用戶定義在關係表上的一類由事件驅動的資料庫對象,也是一種保證數據完整性的方法。

觸發器一旦定義,無須用戶調用,任何對錶的修改操作均由資料庫伺服器自動激活相應的觸發器。

一、創建觸發器

CREATE TRIGGER trigger_name trigger_time trigger_event
	ON tbl_name FOR EACH ROW trigger_body
  • trigger_time
    • BEFORE
    • AFTER
  • trigger_event
    • INSERT
    • UPDATE
    • DELETE
  • tbl_name
    • 用於指定與觸發器相關聯的表名,必須引用永久性表
    • 不能將觸發器與臨時表或視圖關聯起來
    • 同一個表不能擁有兩個具有相同觸發時刻和事件的觸發器
  • 在觸發器的創建中,每個表每個事件每次只允許一個觸發器
  • 每個表最多支持6個觸發器,即每條 INSERT、UPDATE 和 DELETE 的“之前”與“之後”
  • 單一觸發器不能與多個事件或多個表關聯

例子:在資料庫 mysql_test 的表 customers 中創建一個觸發器 customers_insert_trigger,用於每次向表 customers 插入一行數據時,將用戶變數 str 的值設置為 “one customer added!”。

mysql> use mysql_test;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> create trigger mysql_test.customers_insert_trigger after insert
    -> on mysql_test.customers for each row set @str='one customer added!';
Query OK, 0 rows affected (0.02 sec)

mysql> insert into mysql_test.customers
    -> values(null,'萬華','F','長沙市','芙蓉區');
ERROR 1136 (21S01): Column count doesn't match value count at row 1
mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field        | Type     | Null | Key | Default | Extra          |
+--------------+----------+------+-----+---------+----------------+
| cust_id      | int      | NO   | PRI | NULL    | auto_increment |
| cust_name    | char(20) | YES  |     | NULL    |                |
| cust_sex     | char(1)  | YES  |     | M       |                |
| cust_city    | char(10) | NO   |     | Beijing |                |
| cust_address | char(50) | YES  |     | NULL    |                |
| cust_contact | char(50) | YES  |     | NULL    |                |
+--------------+----------+------+-----+---------+----------------+
6 rows in set (0.01 sec)

mysql> alter table mysql_test.customers drop column cust_contact;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> desc customers;
+--------------+----------+------+-----+---------+----------------+
| Field        | Type     | Null | Key | Default | Extra          |
+--------------+----------+------+-----+---------+----------------+
| cust_id      | int      | NO   | PRI | NULL    | auto_increment |
| cust_name    | char(20) | YES  |     | NULL    |                |
| cust_sex     | char(1)  | YES  |     | M       |                |
| cust_city    | char(10) | NO   |     | Beijing |                |
| cust_address | char(50) | YES  |     | NULL    |                |
+--------------+----------+------+-----+---------+----------------+
5 rows in set (0.01 sec)

mysql> insert into mysql_test.customers values(null,'萬華','F','長沙市','芙蓉區');
Query OK, 1 row affected (0.00 sec)

mysql> select @str;
+---------------------+
| @str                |
+---------------------+
| one customer added! |
+---------------------+
1 row in set (0.00 sec)

mysql>

二、刪除觸發器

DROP TRIGGER [IF EXISTS] [schema_name.] trigger_name

例子:刪除資料庫 mysql_test 中的觸發器 customers_insert_trigger。

mysql> drop trigger if exists mysql_test.customers_insert_trigger;
Query OK, 0 rows affected (0.00 sec)

mysql>
  • 當刪除一個表的同時,也會自動地刪除該表上的觸發器,且觸發器不能更新或覆蓋,為了修改一個觸發器,必須先刪除它,然後再重新創建。

三、使用觸發器

1 INSERT 觸發器

  • 在 INSERT 觸發器代碼內,可引用一個名為 NEW(不區分大小寫)的虛擬表,來訪問被插入的行。
  • 在 BEFORE INSERT 觸發器中,NEW 中的值也可以被更新,即允許更改被插入的值(只要具有對應的操作許可權)。
  • 對於 AUTO_INCREMENT 列,NEW 在 INSERT 執行之前包含的是0值,在 INSERT 執行之後將包含新的自動生成值。

例子:在資料庫 mysql_test 的表 customers 中重新創建觸發器 customers_insert_trigger,用於每次向表 customers插入一行數據時,將用戶變數 str 的值設置為新插入客戶的 id 號。

mysql> create trigger mysql_test.customers_insert_trigger after insert
    -> on mysql_test.customers for each row set @str=new.cust_id;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into mysql_test.customers values(null,'曾偉','F','長沙市','芙蓉區');
Query OK, 1 row affected (0.00 sec)

mysql> select @str;
+------+
| @str |
+------+
|  911 |
+------+
1 row in set (0.00 sec)

mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address |
+---------+-----------+----------+-----------+--------------+
|     901 | 張三      | F        | 北京市    | 武漢市       |
|     902 | 李四      | M        | 武漢市    | 上海市       |
|     903 | 李四      | M        | Beijing   | 上海市       |
|     904 | 李四      | M        | Beijing   | 上海市       |
|     910 | 萬華      | F        | 長沙市    | 芙蓉區       |
|     911 | 曾偉      | F        | 長沙市    | 芙蓉區       |
+---------+-----------+----------+-----------+--------------+
6 rows in set (0.00 sec)

mysql>

2 DELETE 觸發器

  • 在 DELETE 觸發器代碼內,可以引用一個名為 OLD(不區分大小寫)的虛擬表,來訪問被刪除的表。
  • OLD 中的值全部是只讀的,不能被更新。

3 UPDATE 觸發器

  • 在 UPDATE 觸發器代碼內,可以引用一個名為 OLD(不區分大小寫)的虛擬表訪問以前(UPDATE 語句執行前)的值,也可以引用一個名為 NEW(不區分大小寫)的虛擬表訪問新更新的值。
  • 在 BEFORE UPDATE 觸發器中,NEW 中的值可能也被更新,即允許更改將要用於 UPDATE 語句中的值(只要具有對應的操作許可權)。
  • OLD 中的值全部是只讀的,不能被更新。
  • 當觸發器涉及對觸發表自身的更新操作時,只能使用 BEFORE UPDATE 觸發器,而 AFTER UPDATE 觸發器將不被允許。

例子:在資料庫 mysql_test 的表 customers 中創建一個觸發器 customers_update_trigger,用於每次更新表 customers時,將該表中 cust_address 列的值設置為 cust_contact 列的值。

mysql> create trigger mysql_test.customers_update_trigger before update
    -> on mysql_test.customers for each row
    -> set new.cust_address=old.cust_contact;
ERROR 1054 (42S22): Unknown column 'cust_contact' in 'OLD'
mysql> alter table mysql_test.customers
    -> add column cust_contact char(50) null;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> create trigger mysql_test.customers_update_trigger before update on mysql_test.customers for each row set new.cust_address=old.cust_contact;
Query OK, 0 rows affected (0.01 sec)

mysql> update mysql_test.customers set cust_address='武漢市' where cust_name='曾偉';
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> select cust_address from mysql_test.customers where cust_name='曾偉';
+--------------+
| cust_address |
+--------------+
| NULL         |
+--------------+
1 row in set (0.00 sec)

mysql> select * from customers;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
|     901 | 張三      | F        | 北京市    | 武漢市       | NULL         |
|     902 | 李四      | M        | 武漢市    | 上海市       | NULL         |
|     903 | 李四      | M        | Beijing   | 上海市       | NULL         |
|     904 | 李四      | M        | Beijing   | 上海市       | NULL         |
|     910 | 萬華      | F        | 長沙市    | 芙蓉區       | NULL         |
|     911 | 曾偉      | F        | 長沙市    | NULL         | NULL         |
+---------+-----------+----------+-----------+--------------+--------------+
6 rows in set (0.00 sec)

mysql>

第三節 安全性與訪問控制

一、用戶賬號管理

查看MySQL資料庫的使用者賬號

mysql> select user from mysql.user;
+------------------+
| user             |
+------------------+
| root             |
| mysql.infoschema |
| mysql.session    |
| mysql.sys        |
+------------------+
4 rows in set (0.01 sec)

1 創建用戶賬號

CREATE USER user[IDENTIFIED BY [PASSWORD] 'password']
  • "user" 格式:'user_name'@'host_name'
  • 沒指定主機名,則主機名會預設為是"%",其表示一組主機

例子:在MySQL伺服器中添加兩個新的用戶,其用戶名分別為 zhangsan 和 lisi,他們的主機名均為 localhost,用戶 zhangsan的口令設置為明文 123,用戶 lisi的口令設置為對明文456使用 PASSWORD()函數加密返回的散列值。

# 查看 mysql 初始的密碼策略
mysql> show variables like 'validate_password%';
+--------------------------------------+--------+
| Variable_name                        | Value  |
+--------------------------------------+--------+
| validate_password.check_user_name    | ON     |
| validate_password.dictionary_file    |        |
| validate_password.length             | 8      |
| validate_password.mixed_case_count   | 1      |
| validate_password.number_count       | 1      |
| validate_password.policy             | MEDIUM |
| validate_password.special_char_count | 1      |
+--------------------------------------+--------+
7 rows in set (0.01 sec)

# 設置密碼的驗證強度等級,設置 validate_password_policy 的全局參數為 LOW 
mysql> set global validate_password.policy=LOW;
Query OK, 0 rows affected (0.01 sec)


mysql>  create user 'zhangsan'@'localhost' identified by '12345678';
Query OK, 0 rows affected (0.01 sec)

mysql> select md5(12345678);  # MySQL 8.0+以上版本 password() 不可用
+----------------------------------+
| md5(12345678)                    |
+----------------------------------+
| 25d55ad283aa400af464c76d713c07ad |
+----------------------------------+
1 row in set (0.00 sec)

mysql> create user 'lisi'@'localhost' identified by '12345678';
Query OK, 0 rows affected (0.00 sec)

mysql>

官網:https://dev.mysql.com/doc/refman/8.0/en/create-user.html

CREATE USER
  'jeffrey'@'localhost' IDENTIFIED WITH mysql_native_password
                                   BY 'new_password1',
  'jeanne'@'localhost' IDENTIFIED WITH caching_sha2_password
                                  BY 'new_password2'
  REQUIRE X509 WITH MAX_QUERIES_PER_HOUR 60
  PASSWORD HISTORY 5
  ACCOUNT LOCK;
  • 要使用 CREATE USER 語句,必須擁有 MySQL 中 mysql 資料庫的 INSERT 許可權或全局 CREATE USER 許可權。
  • 使用 CREATE USER 語句創建一個用戶賬號後,會在系統自身的mysql資料庫的user表中添加一條新記錄。如果創建的賬戶已經存在,則語句執行會出現錯誤。
  • 如果兩個用戶具有相同的用戶名和不同的主機名,MySQL會將他們視為不同的用戶,並允許為這兩個用戶分配不同的許可權集合。
  • 如果在 CREATE USER 語句的使用中,沒有為用戶指定口令,那麼MySQL允許該用戶可以不使用口令登錄系統,然而從安全的角度而言,不推薦這種做法。
  • 新創建的用戶擁有的許可權很少。

2 刪除用戶

DROP USER user [,user]...

例子:刪除lisi用戶

mysql> drop user lisi;
ERROR 1396 (HY000): Operation DROP USER failed for 'lisi'@'%'
mysql> drop user lisi@localhost;
Query OK, 0 rows affected (0.00 sec)

mysql>
  • DROP USER 語句可用於刪除一個或多個MySQL賬戶,並消除其許可權。
  • 要使用DROP USER 語句,必須擁有MySQL中mysql資料庫的DELETE許可權或全局 CREATE USER 許可權。
  • 在 DROP USER 語句的使用中,如果沒有明確地給出賬戶的主機名,則該主機名會預設為是 %。
  • 用戶的刪除不會影響到他們之前所創建的表、索引或其他資料庫對象,這是因為MySQL並沒有記錄是誰創建了這些對象。

3 修改用戶賬號

RENAME USER old_user TO new_user [, old_user TO new_user] ...

例子:將用戶 zhangsan 的名字修改成 wangwu

mysql> rename user 'zhangsan'@'localhost' to 'wangwu'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql>

  • RENAME USER 語句用於對原有MySQL賬戶進行重命名。
  • 要使用 RENAME USER 語句,必須擁有MySQL中mysql資料庫的UPDATE許可權或全局CREATE USER 許可權。
  • 倘若系統中舊賬戶不存在或者新賬戶已存在,則語句執行會出現錯誤。

4 修改用戶口令

SET PASSWORD [FOR user] =
	{
	PASSWORD('new_password') | 'encrypted password'
	}

例子:

mysql> set password for 'wangwu'@'localhost' = '88888888';
Query OK, 0 rows affected (0.00 sec)

mysql>

二、賬戶許可權管理

mysql> select user from mysql.user;
+------------------+
| user             |
+------------------+
| root             |
| mysql.infoschema |
| mysql.session    |
| mysql.sys        |
| wangwu           |
+------------------+
5 rows in set (0.00 sec)

mysql> show grants for 'wangwu'@'localhost';
+--------------------------------------------+
| Grants for wangwu@localhost                |
+--------------------------------------------+
| GRANT USAGE ON *.* TO `wangwu`@`localhost` |
+--------------------------------------------+
1 row in set (0.01 sec)

mysql>

1 許可權的授予

GRANT
	priv_type [(column_list)]
		[, priv_type [(column_list)]] ...
  ON [object_type] priv_level
  TO user_specification [, user_specification] ...
  [WITH GRANT OPTION]
  • “priv_level”:用於指定許可權的級別
    • "*" 表示當前資料庫中的所有表
    • "*.*" 表示所有資料庫中的所有表
    • "db_name.*" 表示某個資料庫中的所有表
  • 如果許可權被授予給一個不存在的用戶,MySQL會自動執行一條 CREATE USER 語句來創建這個用戶,但同時必須為該用戶指定口令。
  • "user_specification" 是 TO 子句中的具體描述部分
    • user[IDENTIFIED BY [PASSWORD] 'password']

例子:授予用戶 zhangsan 在資料庫 mysql_test 的表 customers 上擁有對列 cust_id 和列 cust_name 的 SELECT 許可權

➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1105
Server version: 8.0.32 Homebrew

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> grant select (cust_id, cust_name) on mysql_test.customers to 'zhangsan'@'localhost';
ERROR 1410 (42000): You are not allowed to create a user with GRANT
mysql> select user from mysql.user;
+------------------+
| user             |
+------------------+
| root             |
| mysql.infoschema |
| mysql.session    |
| mysql.sys        |
| wangwu           |
+------------------+
5 rows in set (0.00 sec)

mysql> rename user 'wangwu'@'localhost' to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)

mysql> grant select (cust_id, cust_name) on mysql_test.customers to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)


➜ mysql -uzhangsan -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1107
Server version: 8.0.32 Homebrew

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from mysql_test.customers;
ERROR 1142 (42000): SELECT command denied to user 'zhangsan'@'localhost' for table 'customers'
mysql> select cust_id,cust_name from mysql_test.customers;
+---------+-----------+
| cust_id | cust_name |
+---------+-----------+
|     901 | 張三      |
|     902 | 李四      |
|     903 | 李四      |
|     904 | 李四      |
|     910 | 萬華      |
|     911 | 曾偉      |
+---------+-----------+
6 rows in set (0.00 sec)

例子2:創建 liming 和 huang 兩個用戶,並設置對應的系統登錄口令,同時授予他們在資料庫 mysql_test 的表 customers 上擁有 SELECT 和 UPDATE 的許可權。

mysql> grant select, update on mysql_test.customers to 'liming'@'localhost';
ERROR 1410 (42000): You are not allowed to create a user with GRANT 
# mysql 8 最新的MySQL8不允許直接創建並授權,必須先讓自己有GRANT許可權,然後創建用戶,再授權。

mysql> SELECT host,user,Grant_priv,Super_priv FROM mysql.user;
+-----------+------------------+------------+------------+
| host      | user             | Grant_priv | Super_priv |
+-----------+------------------+------------+------------+
| %         | root             | Y          | Y          |
| localhost | mysql.infoschema | N          | N          |
| localhost | mysql.session    | N          | Y          |
| localhost | mysql.sys        | N          | N          |
| localhost | zhangsan         | N          | N          |
+-----------+------------------+------------+------------+
5 rows in set (0.00 sec)

mysql>

例子3:授予zhangsan 可以在資料庫 mysql_test 中執行所有資料庫操作的許可權

mysql> grant all on mysql_test.* to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)

例子4:授予 zhangsan 創建用戶的許可權

mysql> grant create user on *.* to 'zhangsan'@'localhost';
Query OK, 0 rows affected (0.01 sec)

mysql>

"priv_type" 的使用

  • 授予表許可權時,可以指定為以下值
    • SELECT
    • INSERT
    • DELETE
    • UPDATE
    • REFERENCES
    • CREATE
    • ALTER
    • INDEX
    • DROP
    • ALL 或 ALL PRIVILEGES
  • 授予列許可權時:
    • SELECT
    • INSERT
    • UPDATE
    • 許可權的後面需要加上列名列表 column_list
  • 授予資料庫許可權時:
    • SELECT
    • INSERT
    • DELETE
    • UPDATE
    • REFERENCES
    • CREATE
    • ALTER
    • INDEX
    • DROP
    • CREATE TEMPORARY TABLES
    • CREATE VIEW
    • SHOW VIEW
    • CREATE ROUTINE
    • ALTER ROUTINE
    • EXECUTE ROUTINE
    • LOCK TABLES
    • ALL 或 ALL PRIVILEGES
  • 授予用戶許可權時:
    • 授予資料庫許可權時的所有值
    • CREATE USER
    • SHOW DATABASES

2 許可權的轉移

  • 許可權的轉移可以通過在 GRANT 語句中使用 WITH 子句來實現。
  • 如果將 WITH 子句指定為關鍵字 "WITH GRANT OPTION",則表示 TO 子句中所指定的所有用戶都具有把自己所擁有授予給其他用戶的權利,而無論那些其他用戶是否擁有該許可權。

例子:

~
➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1173
Server version: 8.0.32 Homebrew

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> grant select,update on mysql_test.customers to 'zhou'@'localhost' identified by '123' with grant option;
ERROR 1064 (42000): 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 'identified by '123' with grant option' at line 1
# mysql 8.0+ 報錯 先創建用戶 後授權


mysql> create user 'zhou'@'localhost' identified by '12345678';
Query OK, 0 rows affected (0.01 sec)

mysql> grant select,update on mysql_test.customers to 'zhou'@'localhost' identified by '12345678' with grant option;
ERROR 1064 (42000): 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 'identified by '12345678' with grant option' at line 1

mysql> grant select,update on mysql_test.customers to 'zhou'@'localhost'  with grant option;
Query OK, 0 rows affected (0.01 sec)

mysql>

3許可權的撤銷

  • 當需要回收某些特定的許可權時
REVOKE
	priv_type [(column_list)]
		[, priv_type [(column_list)]] ...
  ON [object_type] priv_level
  FROM user [, user] ...
  • 當需要回收特定用戶的所有許可權時
REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user]... 

例子:

mysql> revoke select on mysql_test.customers from 'zhou'@'localhost';
Query OK, 0 rows affected (0.00 sec)

mysql>

  • 要使用 REVOKE 語句,必須擁有 mysql 資料庫的全局 CREATE USER 許可權或 UPDATE 許可權

第四節 事物與併發控制

事務就是為保證數據的一致性而產生的一個概念和基本手段

一、事務的概念

  • 所謂事務是用戶定義的一個數據操作序列,這些操作可作為一個完整的工作單元,要麼全部執行,要麼全部不執行,是一個不可分割的工作單位。
  • 事務與程式的區別:
    • 程式是靜止的
    • 事務是動態的,是程式的執行而不是程式本身
    • 同一程式的多個獨立執行可以同時進行,而每一步執行則是一個不同的事務

二、事務的特征 ACID

  • 原子性(Atomicity)
    • 事務是不可分割的最小工作單位,所包含的這些操作是一個整體
    • 要麼全做,要麼全不做
  • 一致性(Consistency)
    • 完整性約束
  • 隔離性(Isolation)
    • 事務彼此獨立的、隔離的
    • 可串列性 串列調度
  • 持續性(Durability)
    • 永久性(Permanence)

例子:依據事物的ACID特性,分析並編寫銀行資料庫系統中的轉賬事務T:從賬戶A轉賬S金額資金到賬戶B。

BEGIN TRANSACTION
	read(A);
	A=A-S;
	write(A);
	if(A<0) ROLLBACK
	else {
	read(B);
	B=B+S
	write(B);
	COMMIT;
	}

三、併發操作問題

事務是併發控制的基本單位,保證事務的ACID特征是事務處理的重要任務,而事務的ACID特征可能遭到破壞的原因之一是多個事務對資料庫的併發操作造成的。

完整性檢驗可以保證一個事務單獨執行時,若輸入的資料庫狀態是正確的,則其輸出的資料庫狀態也是正確的。

當多個事務交錯執行時,可能出現不一致問題,這也稱為併發操作問題。

(1)丟失更新

(2)不可重覆讀

(3)讀“臟”數據

併發控制機制就是用正確的方式調度併發操作,使一個用戶事務的執行不受其他事務的干擾,從而避免造成數據的不一致性。

解決併發操作所帶來的數據不一致性問題的方法有封鎖、時間戳、樂觀控製法和多版本併發控制等。

四、封鎖

1 鎖
  • 一個鎖實質上就是允許或阻止一個事務對一個數據對象的存取特權。
  • 基本的封鎖類型有兩種:
    • 排他鎖(Exclusive Look,X鎖) 寫操作
    • 共用鎖(Shared Lock,S鎖) 讀操作
2 用封鎖進行併發控制

封鎖的工作原理如下:

  • 若事務T對數據D加了X鎖,則所有別的事務對數據D的鎖請求都必須等待直到事務T釋放鎖。
  • 若事務T對數據D加了S鎖,則別的事務還可對數據D請求S鎖,而對數據D的X鎖請求必須等待直到事務T釋放鎖
  • 事務執行資料庫操作時都要先請求相應的鎖,即對讀請求S鎖,對更新(插入、刪除、修改)請求X鎖。這個過程一般是由DBMS在執行操作時自動隱含地進行。
  • 事務一直占有獲得的鎖直到結束(COMMIT 或 ROLLBACK)時釋放。
3 封鎖的粒度

通常由粒度來描述封鎖的數據單元的大小。

大多數高性能系統都選擇折中的鎖粒度,至於哪一層最合適,則與應用環境下事務量、數據量及數據的易變特征等都緊密相關。

4 封鎖的級別

封鎖的級別又稱為一致性級別或隔離度。

  • 0級封鎖:封鎖的事物不重寫其他非0級封鎖事務的未提交的更新數據。這種狀態實際上實用價值不大。
  • 1級封鎖:被封鎖的實物不允許重寫未提交的更新數據。這防止了丟失更新的發生。
  • 2級封鎖:被封鎖的事物即不重寫也不讀未提交的更新數據。這除了1級封鎖的效果外還防止了讀臟數據。
  • 3級封鎖:被封鎖的事物不讀未提交的更新數據,不寫任何(包括讀操作)未提交數據。
    • 這除了包含2級封鎖外,還不寫未提交的讀數據,因而防止了不可重讀的問題。
    • 這是嚴格的封鎖,它保證了多個事務併發執行的“可串列化”。
5 活鎖與死鎖

封鎖帶來的一個重要問題是可能引起“活鎖”與“死鎖”。

在併發事務處理過程中,由於鎖會使一事務處於等待狀態而調度其他事務處理,因而該事務可能會因優先順序低而永遠等待下去,這種現象稱為“活鎖”。

活鎖問題的解決與調度演算法有關,一種最簡單的辦法是“先來先服務”。

兩個以上事務迴圈等待被同組中另一事務鎖住的數據單元的情形,稱為“死鎖”。

在任何一個多任務程式設計系統中,死鎖總是潛在的,所以在這種環境下的DBMS需要提供死鎖預防、死鎖檢測和死鎖發生後的處理技術與方法。

預防死鎖的方法:

  • 一次性鎖請求
  • 鎖請求排序
  • 序列化處理
  • 資源剝奪

對待死鎖的另一種辦法是不去防止,而讓其發生並隨時進行檢測,一旦檢測到系統已發生了死鎖再進行解除處理。

死鎖檢測可以用圖論的方法實現,並以正在執行的事物為結點。

6 可串列性

若一個調度等價於某一串列高度,即它所產生的結果與某一串列調度的結果一樣,則說調度是可串列化的(Serializable)。

一組事務的串列調度不是唯一的,因而可串列化的調度也不是唯一的。

通常,在資料庫系統中,可串列性就是併發執行的正確性準則,即當且僅當一組事務的併發執行調度是可串列化的,才認為它們是正確的。

7 兩段封鎖法

採用兩段封鎖法(Two-Phase Locking,2PL)是一種最簡單而有效的保障封鎖其調度是可串列性的方法。

兩段封鎖法是事務遵循兩段鎖協議的調度方法。

協議就是所有事務都必須遵循的關於基本操作執行順序的一種限制。

兩段鎖協議規定在任何一個事務中,所有加鎖操作都必須在所有釋放鎖操作之前。

事務劃分成如下兩個階段:

  • 發展(Growing)或加鎖階段
  • 收縮(Shrinking)或釋放鎖階段

定理6.1:遵循兩段鎖協議的事務的任何併發調度都是可串列化的。

2PL 是可串列化的充分條件,不是必要條件,即存在不全是2PL的事務的可串列化調度。

第五節 備份與恢復

資料庫的實際使用過程中,存在著一些不可預估的因素:

  • 電腦硬體故障
  • 電腦軟體故障
  • 病毒
  • 人為操作
  • 自然災害
  • 盜竊

資料庫備份是指通過導出數據或者複製表文件的方式來製作資料庫的複本

資料庫恢復則是當資料庫出現故障或遭到破壞時,將備份的資料庫載入到系統,從而使資料庫從錯誤狀態恢復到備份時的正確狀態。

資料庫的恢復是以備份為基礎的。它是與備份相對應的系統維護和管理操作。

1 使用 SELECT INTO...OUTFILE 語句備份數據

SELECT * INTO OUTFILE 'file_name' export_options
	| INTO DUMPFILE 'file_name'

其中,語法項“export_options” 的格式是:

[FIELDS 
	[TERMINATED BY 'string']
	[[OPTIONALLY] ENCLOSED BY 'char']
	[ESCAPED BY 'char']
]
[LINES TERMINATED BY 'string']
  • 在文件中,導出的數據行會以一定的形式存儲,其中空值是用"\N" 表示。

2 使用 LOAD DATA...INFILE 語句恢複數據

LOAD DATA INFILE 'file_name.txt'
	INTO TABLE tbl_name
	[FIELDS
  	[TERMINATED BY 'string']
  	[[OPTIONALLY] ENCLOSED BY 'char']
  	[ESCAPED BY 'char']
  ]
  [LINES
  	[STARTING BY 'string']
  	[TERMINATED BY 'string']
  ]

例子:備份資料庫mysql_test中表customers的全部數據。

➜ mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2354
Server version: 8.0.32 Homebrew

Copyright (c) 2000, 2023, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select * from mysql_test.customers
    -> into outfile '/Users/qiaopengjun/backupfile.txt'
    -> fields terminated by ','
    -> optionally enclosed by ""
    -> lines terminated by '?';
ERROR 1290 (HY000): The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
mysql> show variables like '%secure_file_priv%';
+------------------+-------+
| Variable_name    | Value |
+------------------+-------+
| secure_file_priv | NULL  |
+------------------+-------+
1 row in set (0.01 sec)

mysql> show global variables like "%datadir%";
+---------------+--------------------------+
| Variable_name | Value                    |
+---------------+--------------------------+
| datadir       | /opt/homebrew/var/mysql/ |
+---------------+--------------------------+
1 row in set (0.02 sec)

mysql> select * from mysql_test.customers into outfile '/Users/qiaopengjun/backupfile.txt' fields terminated by ',' optionally enclosed by "" lines terminated by '?';
ERROR 2013 (HY000): Lost connection to MySQL server during query
No connection. Trying to reconnect...
Connection id:    8
Current database: *** NONE ***

Query OK, 6 rows affected (0.02 sec)

mysql> show variables like '%secure%';
+--------------------------+---------------------+
| Variable_name            | Value               |
+--------------------------+---------------------+
| require_secure_transport | OFF                 |
| secure_file_priv         | /Users/qiaopengjun/ |
+--------------------------+---------------------+
2 rows in set (0.01 sec)

mysql>

mysql> select * from mysql_test.customers into outfile '/Users/qiaopengjun/backupfile.txt' fields terminated by ',' optionally enclosed by "" lines terminated by '?';
Query OK, 6 rows affected (0.01 sec)

mysql>

mysql複製表的兩種方式:

第一、只複製表結構到新表
create table 新表 select * from 舊表 where 1=2
或者
create table 新表 like 舊表

第二、複製表結構及數據到新表
create table新表 select * from 舊表

homebrew/var/mysql on  stable took 5.4s
➜ mysql --verbose --help | grep my.cnf
                      order of preference, my.cnf, $MYSQL_TCP_PORT,
/etc/my.cnf /etc/mysql/my.cnf /opt/homebrew/etc/my.cnf ~/.my.cnf

homebrew/var/mysql on  stable
➜

brew services restart mysql

將備份數據導入到一個和customers表結構相同的空表 customers_copy 中

mysql> create table customers_copy select * from customers where 1=2;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> show tables;
+----------------------+
| Tables_in_mysql_test |
+----------------------+
| customers            |
| customers_copy       |
| customers_view       |
| orders               |
| seller               |
+----------------------+
5 rows in set (0.00 sec)

mysql> load data infile '/Users/qiaopengjun/backupfile.txt' into table mysql_test.customers_copy fields terminated by ',' optionally enclosed by "" lines terminated by '?';
Query OK, 6 rows affected (0.01 sec)
Records: 6  Deleted: 0  Skipped: 0  Warnings: 0

mysql> select * from customers_copy;
+---------+-----------+----------+-----------+--------------+--------------+
| cust_id | cust_name | cust_sex | cust_city | cust_address | cust_contact |
+---------+-----------+----------+-----------+--------------+--------------+
|     901 | 張三      | F        | 北京市    | 武漢市       | NULL         |
|     902 | 李四      | M        | 武漢市    | 上海市       | NULL         |
|     903 | 李四      | M        | Beijing   | 上海市       | NULL         |
|     904 | 李四      | M        | Beijing   | 上海市       | NULL         |
|     910 | 萬華      | F        | 長沙市    | 芙蓉區       | NULL         |
|     911 | 曾偉      | F        | 長沙市    | NULL         | NULL         |
+---------+-----------+----------+-----------+--------------+--------------+
6 rows in set (0.00 sec)

mysql>

  • 在多個用戶同時使用MySQL資料庫的情況下,為了得到一個一致的備份,需要在指定的表上使用 LOCK TABLES table_name READ 語句做一個讀鎖定,以防止在備份過程中表被其他用戶更新。
  • 當恢複數據時,則需要使用 LOCK TABLES table_name WRITE 語句做一個寫鎖定,以避免發生數據衝突。
  • 在資料庫備份或恢復完畢之後需要使用 UNLOCK TABLES 語句對該表進行解鎖。

本文來自博客園,作者:QIAOPENGJUN,轉載請註明原文鏈接:https://www.cnblogs.com/QiaoPengjun/p/17279396.html


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1.1 關於C# C#只是一種簡單安全的新型面向對象語言,繼承了C的語法風格和C++的面向對象特性,不再提供對指針類型的支持(因此程式不可隨便訪問記憶體地址空間)、不再支持多重繼承; C#的誕生意義是生成面向.NET Framework環境的代碼,身為編程語言的一種,它作為開發工具而存在,本身並不是. ...
  • 1. 編寫函數,實現列印綠色OK和紅色FAILED 判斷是否有參數,存在為Ok,不存在為FAILED [root@template shellScript]# cat ex1.sh # 編寫函數,實現列印綠色OK和紅色FAILED 判斷是否有參數,存在為Ok,不存在為FAILED #!/bin/ba ...
  • 一、常規操作 1、創建文件夾 mkdir 文件夾名稱 2、創建文件或編輯文件 在目標文件夾中執行 vi 文件名.尾碼 # i (進入可編輯模式) # ESC (按Esc按鍵,退出編輯模式) # :q (未作任何編輯,直接退出) # :q! (強制退出) # :wq (保存退出) 3、文件夾或文件賦權 ...
  • 前言 最近電腦重新安裝nmap,但是圖形化界面無法運行,如圖所示: 是因為用戶名稱中存在中文字元。 接下來就親自實操一下如何將Windows操作系統用戶名的中文名稱修改為英文名稱。 一、控制面板修改電腦名 (1):桌面左下角搜索框搜索控制面板(2):打開控制面板,點擊用戶帳戶下的更改賬戶類型 (3) ...
  • 今天鹹魚給大家分享個源碼編譯安裝 Nginx 的 shell 腳本 這個 shell 腳本可重覆執行 完整源碼放在最後 定義一個變數來存放 nginx 版本號 version=1.15.4 nginx 下載地址:http://nginx.org/download/ 下列函數功能則是判斷當前步驟是否執 ...
  • 一、為什麼要線程同步 在Linux 多線程編程中,線程同步是一個非常重要的問題。如果線程之間沒有正確地同步,就會導致程式出現一些意外的問題,例如: 競態條件(Race Condition):多個線程同時修改同一個共用變數,可能會導致不可預測的結果,因為線程的執行順序是不確定的。 死鎖(Deadloc ...
  • 這篇主要介紹對於SOP8,SOP10,SOP16封裝的PY32F002A/PY32F003, 沒有BOOT0的情況如何修改Option Bytes, 以及如何在物理管腳上使用不同的PIN ...
  • 訪問命令行(command line interface,CLI) Linux控制台 1)Linux系統啟動時,會自動創建多個虛擬控制台。虛擬控制台是運行在Linux系統記憶體中的終端會話。多數Linux發行版會啟動5~6個 2)通常必須按下Ctrl+Alt組合鍵,然後再按一個功能鍵(F1~F7)來進 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...