
6
在資料庫管理系統(DBMS)中,資料庫交易(Database Transaction)是指一組資料庫操作,被視為單個工作單元,要麼完全執行,要麼完全不執行的過程。資料庫交易必須遵循ACID屬性,才可以被提交
PS 使用 COMMIT 命令,才會確保這些更改永久保存在資料庫中
Atomicity (原子性) : 資料操作不可分割。一次 transaction 只能成功或失敗
Consistency (一致性):transaction 完成前後,資料都必須永遠符合 schema 的規則,如果錯誤,可通過調整 schema 來維護
Isolation (隔離性):資料庫允許多個 transactions 同時對資料交叉執行,但執行不應互相干擾、不會導致數據的不一致
數據腐敗
# 在創建索引的同時,有一個新的用戶被添加到數據庫中,但此修改尚未納入索引。這將導致索引中缺少新用戶的數據,即數據腐敗
# 創建用戶表
CREATE TABLE users (user_id INT PRIMARY KEY, username VARCHAR(255));
# 添加一個用戶
INSERT INTO users (user_id, username) VALUES (1, 'John');
# 創建用戶ID索引
CREATE INDEX idx_user_id ON users (user_id);
# 同時添加另一個用戶,但在創建索引之前
INSERT INTO users (user_id, username) VALUES (2, 'Jane');
有許多隔離級別,可以防止數據腐敗
— Serializable(序列化) : 最高的隔離級別,可以確保事務的【完全隔離】,對所有讀取的資料加鎖,並確保其他交易無法對這些資料進行讀取或寫入操作,但也可能導致系統性能下降,因為它阻止了同時執行多個事務 (PS SELECT FOR UPDATE 鎖定特定行; Serializable 是一個整體的數據庫隔離機制,確保整個事務的一致性和隔離性)
— Repeatable Read(可重複讀取) : 即使有其他事務對資料進行了更新,也不會讀取到不一致的結果,但仍然可能會出現幻讀的情況
— Snapshot (快照) : 事務可以查看從開始到結束的數據快照,即使其他事務正在對數據進行更改,當前事務也可以看到開始時的數據狀態。如果多個事務正在對同一行進行更改,可能會發生衝突。在這種情況下,通常會使用鎖定機制或版本控制 (PS MYSQL 沒有,POSTGRE SQL 可以使用 SYSTEM_TIME AS OF TIMESTAMP ‘2023-10-10 12:00:00’)
— Read Committed(已提交讀取) : 讀取操作【僅返回】【已提交】的數據,並且不會讀取到未提交的數據,避免髒讀和不可重複讀的問題,但仍然可能會出現幻讀的情況
–Read Uncommitted(未提交讀取) : 允許事務讀取未提交的變更,可能導致髒讀、不可重複讀和幻讀
# 設置隔離級別,一定要先 BEGIN TRANSACTION
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
# 如果要查詢事務時間
SELECT * FROM table_name AS OF TIMESTAMP 'yyyy-mm-dd hh:mm:ss';
SELECT * FROM table_name VERSIONS BETWEEN TIMESTAMP 'yyyy-mm-dd hh:mm:ss' AND TIMESTAMP 'yyyy-mm-dd hh:mm:ss';
PS PostgreSQL 在 REPEATABLE READ,可以防止幻讀。但在一些其他的關係型數據庫系統(如 SQL Server、MySQL 和 Oracle)中,只使用 REPEATABLE READ,可能無法完全防止幻讀的發生
# 範例
# read committed,transaction 1 ,在未提交的情況下,一個事務將不會看到另一個事務所進行的任何更改,只能讀取到自己的,會讀出 2-4
# repeatable read transaction 2 會讀出 2-4,但在其他數據庫平台中可能讀出 2-4-5 # repeatable read 只能保證讀取的值保持不變,但不適用於幻讀,因此 t2 可能會讀取到事務 t1 提交的值 5
create table test (id integer)
insert into test (2);
begin transaction 1
t1 - set isolation level read committed
begin transaction 2
t2 - set isolation level repeatable read
t1 - select * from test;
t2 - insert into test (4);
t1 - select * from test;
t1 - insert into test (5);
t2 - select * from test;
t1 - commit;
t2 - select * from test;
t2 - commit;

不同的isolation下,可能會出現不同的讀取現象
— Dirty reads(髒讀):當一個事務讀取了另一個事務更新但尚未提交的資料時發生。第二個事務在第一個事務更新但尚未提交的情況下讀取了資料,導致第二個事務能會讀取到未確認的、無效的資料
CREATE TABLE accounts (account_id INT PRIMARY KEY, balance DECIMAL(10, 2));
INSERT INTO accounts (account_id, balance)VALUES (1, 1000.00);
執行兩個連續的事務(Transaction)
-- 事務 1
START TRANSACTION;
UPDATE accounts
SET balance = 500.00
WHERE account_id = 1;
-- 事務 2
START TRANSACTION;
SELECT * FROM accounts
WHERE account_id = 1;
COMMIT;
-- 回到事務 1,這時事務 2 可能讀取到事務1尚未提交的更新結果,導致事務2看到的資料是無效的或不一致的
COMMIT;
— Non-repeatable reads(不可重複讀):當一個事務在相同的查詢中多次讀取同一行資料時,由於第二個事務已經對資料進行了更改或刪除,兩次讀取的結果會不一致
CREATE TABLE accounts ( account_id INT PRIMARY KEY, balance DECIMAL(10, 2));
INSERT INTO accounts (account_id, balance) VALUES (1, 1000.00);
執行兩個連續的事務(Transaction)
-- 事務 1
START TRANSACTION;
SELECT * FROM accounts
WHERE account_id = 1;
COMMIT;
-- 事務 2
START TRANSACTION;
UPDATE accounts
SET balance = 500.00
WHERE account_id = 1;
COMMIT;
-- 回到事務 1,可能導致在事務1內兩次讀取,出現了不一致的結果
SELECT * FROM accounts
WHERE account_id = 1;
COMMIT;
— Phantom reads(幻讀):當一個事務在相同的查詢中多次讀取同一行資料時,由於第二個事務已經對資料插入了新的資料行,兩次讀取的結果會不一致
CREATE TABLE products(product_id INT PRIMARY KEY, product_name VARCHAR(255));
INSERT INTO products (product_id, product_name) VALUES (1, 'Product A'),(2, 'Product B');
執行兩個連續的事務(Transaction)
-- 事務 1
START TRANSACTION;
SELECT * FROM
products;
COMMIT;
-- 事務 2
START TRANSACTION;
INSERT INTO products
(product_id, product_name) VALUES (3, Product C');
COMMIT;
-- 回到事務 1
SELECT * FROM products;
COMMIT;
— Lost updates(丟失更新):兩個或多個事務同時操作相同資料時,最後只有一個事務的更改被保留,而其他事務的更改被覆蓋並丟失
CREATE TABLE accounts( account_id INT PRIMARY KEY, balance DECIMAL(10,2));
INSERT INTO accounts (account_id, balance) VALUES (1, 1000.00);
執行兩個連續的事務(Transaction)
-- 事務 1
START TRANSACTION;
UPDATE accounts
SET balance = balance - 100
WHERE account_id = 1;
COMMIT;
-- 事務 2
START TRANSACTION;
UPDATE accounts
SET balance = balance - 200
WHERE account_id = 1;
COMMIT;
PS 可以使用適當的【鎖定機制】或其他並發控制機制來協調事務之間對相同資料的操作
-- 事務 1
START TRANSACTION;
SELECT balance INTO @balance
FROM accounts
WHERE account_id = 1
FOR UPDATE;
UPDATE accounts
SET balance = @balance - 100
WHERE account_id = 1;
COMMIT;
-- 事務 2
START TRANSACTION;
SELECT balance INTO @balance
FROM accounts
WHERE account_id = 1
FOR UPDATE;
UPDATE accounts SET balance = @balance - 200
WHERE account_id = 1;
COMMIT;
PS 多版本並發控制(MVCC),是一種更高級的並發控制機制。通過為每個事務創建數據行的多個版本,從而使多個事務能夠同時讀取和修改數據,MVCC會根據每個事務的時間戳或版本信息來處理這些操作,不會產生阻塞或衝突
CREATE TABLE accounts( account_id INT PRIMARY KEY, balance DECIMAL(10, 2))
ENGINE = InnoDB; -- 使用 InnoDB 引擎以支持 MVCC
INSERT INTO accounts (account_id, balance) VALUES (1, 1000.00);
-- 事務 1
START TRANSACTION;
SELECT balance FROM accounts WHERE account_id = 1;
-- 事務 2
START TRANSACTION;
UPDATE accounts
SET balance = balance - 100
WHERE account_id = 1;
COMMIT;
-- 回到事務 1
SELECT balance FROM accounts WHERE account_id = 1;
COMMIT;
PS 樂觀鎖定(Optimistic Locking) ,基於版本標記來檢測並處理衝突
CREATE TABLE accounts( account_id INT PRIMARY KEY, balance DECIMAL(10,2), version INT ) ENGINE = InnoDB; -- 使用 InnoDB 引擎以支持 MVCC
INSERT INTO accounts (account_id, balance, version) VALUES (1, 1000.00, 1);
-- 事務 1
START TRANSACTION;
SELECT balance INTO @balance, version INTO @version FROM accounts WHERE account_id = 1;
-- 事務 2
START TRANSACTION;
SELECT balance INTO @balance, version INTO @version FROM accounts WHERE account_id = 1;
UPDATE accounts
SET balance = @balance - 100, version = @version + 1 WHERE account_id = 1 AND version = @version;
COMMIT;
-- 回到事務 1
UPDATE accounts
SET balance = @balance - 200, version = @version + 1 WHERE account_id = 1 AND version = @version;
COMMIT;
悲觀鎖定(Pessimistic Locking),會直接鎖定資料行,阻止其他事務對資料進行讀取或修改。通常不直接使用版本號,想顯示版本號,可以修改 SELECT 語句
CREATE TABLE accounts( account_id INT PRIMARY KEY, balance DECIMAL(10,2), version INT ) ENGINE = InnoDB; -- 使用 InnoDB 引擎以支持 MVCC
INSERT INTO accounts (account_id, balance, version) VALUES (1, 1000.00, 1);
-- 事務 1
START TRANSACTION;
SELECT balance, version INTO @balance, @version FROM accounts WHERE account_id = 1 FOR UPDATE;
-- 事務 2
START TRANSACTION;
SELECT balance, version INTO @balance, @version FROM accounts WHERE account_id = 1 FOR UPDATE;
UPDATE accounts
SET balance = balance - 100 WHERE account_id = 1;
COMMIT;
-- 回到事務 1
UPDATE accounts
SET balance = balance - 200
WHERE account_id = 1;
COMMIT;
PS 樂觀鎖定(Optimistic Locking) 、悲觀鎖定(Pessimistic Locking)和設置隔離性(Isolation)差異
樂觀鎖定和悲觀鎖定是處理【並發控制】的不同策略,而隔離性則確保事務的執行【不會相互干擾】
樂觀鎖定 : 假設並發衝突不太發生,直到實際進行更新操作時才檢查。在進行更新之前,系統假設沒有其他事務會修改相同的數據。常見的方式是在數據中引入版本號或時間戳,當更新時檢查版本號,如果版本號不匹配,表示有其他事務已經修改了數據
悲觀鎖定 : 假設在進行任何操作之前,數據可能會被其他事務修改,因此在事務開始時就鎖定數據。通常使用各種類型的鎖(例如行鎖或表鎖)來實現。這可能導致性能問題,因為它阻止了其他事務對同一數據進行修改
隔離性 : 指事務之間的相互影響程度。在並發環境中,多個事務可能同時訪問和修改相同的數據,而隔離性確保每個事務看到的數據是一致的
Commit (提交)
可以使用 START TRANSACTION 或 BEGIN 命令開始,做一些變更後用ROLLBACK 命令,更改並回到事務開始的狀態
CREATE DATABASE IF NOT EXISTS try;
USE try;
CREATE TABLE customers (
customer_id INT PRIMARY KEY,
customer_name VARCHAR(255)
);
START TRANSACTION;
INSERT INTO customers (customer_id, customer_name)
VALUES
(1, 'Alice'),
(2, 'Bob'),
(3, 'Charlie'),
(4, 'David');
SELECT * FROM customers;
ROLLBACK;
索引(Index)用於快速查找數據的數據結構
INDEX 標準索引
CREATE TABLE orders (order_id INT PRIMARY KEY, customer_id INT, order_amount DECIMAL(10,2));
# 創建索引
CREATE INDEX idx_customer_id ON orders (customer_id);
# 搜尋
SELECT customer_id, SUM(order_amount) as total_amount FROM orders GROUP BY customer_id;
聯合索引(Composite Index)、包含索引(Covering Index),使查詢更加高效
CREATE TABLE orders (order_id INT PRIMARY KEY, customer_id INT, order_amount DECIMAL(10,2));
# 創建Composite Index)
CREATE INDEX idx_customer_id ON orders (customer_id, order_id);
# 搜尋並使用Covering Index
SELECT customer_id, SUM(order_amount) as total_amount FROM orders GROUP BY customer_id ORDER BY order_id;
PS 如果同上方設置 Composite Index
“`=
EXPLAIN ANALYZE SELECT id FROM orders WHERE customer_id = 10;
第二個索引可能不會被默認使用
EXPLAIN ANALYZE SELECT id FROM orders WHERE order_id = 10;
>PS postgres sql, 包含索引寫法不同
```=
CREATE INDEX idx_customer_id ON orders (customer_id) INCLUDE (order_id);
B+Tree,查詢上的使用方式基本上相同,通常在範圍查詢方面更加有效,更適合用於【範圍查詢和排序操作】,因為節點中只存儲鍵值,而所有數據都存儲在葉節點中
CREATE INDEX bplus_index ON table_name (column_name);
B-Tree,查詢上的使用方式基本上相同,每個節點儲存鍵值和指向子節點的指針
CREATE INDEX b_index ON table_name (column_name);
缺點: 佔用儲存空間、原始數據更改時,INDEX也要更改、過多的索引存在時,可能會導致數據庫的性能下降
CREATE TABLE customers (customer_id INT PRIMARY KEY, customer_name VARCHAR(255));
CREATE INDEX idx_customer_name ON customers (customer_name);
# 更新 table
UPDATE customers SET customer_name = 'New Customer Name' WHERE customer_id = 123;
# 重新構建索引
ALTER TABLE customers DROP INDEX idx_customer_name, ADD INDEX idx_customer_name ON customers (customer_name);
PS 我們說的資料庫通常是 B-Tree (Balanced Tree) ,是一種自平衡的樹狀結構,它允許在 O(log n) 的時間內進行插入、查詢和刪除操作
LSM Tree 是一種日誌結構合併樹,它將數據分為多個層級進行儲存,數據首先被添加到記憶體中的日誌,然後定期合併到磁盤上的較長數據文件中,例如 Elastisearch
PS PostgreSQL、MySQL 在 B-Tree 差異
PostgreSQL : 主索引(Clustered Index)是整個表,在查找主索引中的鍵時,可以立即獲取該鍵所在的完整行,無需進行其他I/O操作、次要索引(Secondary Index)的葉子節點通常包含主鍵的值,索引在查找鍵時,需要進行額外的I/O操作來檢索完整的行數據
MySQL : 主索引(Clustered Index)值是完整的行對象,但與PostgreSQL的情況類似,主索引實際上也是整個表、次要索引(Secondary Index)值是指向主索引中行數據實際位置的指針,意思是次要索引的葉子節點,包含指向主索引中對應行的指針
CREATE TABLE new_table_name LIKE existing_table_name;
# 查看現有表的創建語句,包括索引
SHOW CREATE TABLE existing_table_name;
# 手動添加索引到新表
CREATE INDEX index_name1 ON new_table_name (column1); CREATE INDEX index_name2 ON new_table_name (column2);
PS postgres sql 可以一起添加
CREATE TABLE new_table_name LIKE existing_table_name INCLUDING INDEXES;
SELECT * FROM table_name;
SELECT * FROM table_name WHERE indexed_column = 'value';
Bitmap Index Scan(位圖索引掃描): 可以有效地避免不必要的 I/O 操作和資源浪費
SELECT * FROM table_name WHERE column1 = 'value1' AND column2 = 'value2';
EXPLAIN Analyze table 優化查詢性能 : 用於分析和更新表的統計信息,幫助 MySQL 優化器生成更有效的查詢計劃 (PS DESCRIBE/EXPLAIN 用於瞭解表的結構和設計)
EXPLAIN ANALYZE TABLE table_name;
PS 很常搭配的 AND VS OR
OR操作需要對兩個條件進行分別的搜索,再合併結果,可能導需要更多時間來處理數據,相比之下,AND操作只需要一次搜索,通常比OR操作更有效率
MD5(Message Digest Algorithm 5) : 32位元(128位元)的哈希函數,較短的位元長度和已知的安全漏洞,已經不再被廣泛使用
SHA1(Secure Hash Algorithm 1) : 160位元的哈希函數,SHA1比MD5更安全,但仍存在某些碰撞攻擊風險
SHA2 : SHA2是SHA家族中的一個新版本,包括多個變體(例如SHA-224、SHA-256、SHA-384、SHA-512等)
使用哈希表來快取資料庫查詢的結果,來提高效能
# mysql
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50),
email VARCHAR(100)
);
INSERT INTO users (id, username, email) VALUES
(1, 'user1', 'user1@example.com'),
(2, 'user2', 'user2@example.com'),
(3, 'user3', 'user3@example.com');
import pymysql
from collections import defaultdict
class UserCache:
def __init__(self):
self.cache = defaultdict(dict)
self.db = pymysql.connect(host="your_host", user="your_user", password="your_password", db="your_db")
def get_user(self, user_id):
# 從快取中尋找用戶資訊
if user_id in self.cache['users']:
print("Cache hit!")
return self.cache['users'][user_id]
# 如果快取中沒有,從資料庫查詢
cursor = self.db.cursor()
query = "SELECT * FROM users WHERE id = %s"
cursor.execute(query, (user_id,))
user_data = cursor.fetchone()
if user_data:
# 將查詢結果放入快取
self.cache['users'][user_id] = user_data
return user_data
else:
return None
user_cache = UserCache()
# 第一次查詢
user_data_1 = user_cache.get_user(1)
print(user_data_1)
# 第二次查詢
user_data_1_cached = user_cache.get_user(1)
print(user_data_1_cached)
# 新的查詢
user_data_2 = user_cache.get_user(2)
print(user_data_2)
使用SHA2哈希函數對密碼進行加密,並將加密後的密碼存儲到數據庫中
UPDATE users SET password = SHA2('user_password', 256) WHERE username = 'desired_username';
數據校驗,生成與數據相關的哈希值。如果數據被修改,哈希值會發生變化,提醒您數據已被修改
CHECKSUM TABLE table_name;
數據識別和查詢,識別數據的唯一性,方便查詢或識別中使用
SELECT MD5(column_name) AS hash_value FROM table_name;
數據查找和驗證
SELECT SHA1('your_value');
SELECT * FROM table_name
WHERE hash_column = SHA1('your_value');
使用分區 partitioning,將數據分成多個獨立數據庫(子集)
CREATE TABLE food (id INT PRIMARY KEY, name VARCHAR(255), category VARCHAR(255))
PARTITION BY RANGE (id) ( PARTITION p1 VALUES LESS THAN (3001), PARTITION p2 VALUES LESS THAN MAXVALUE);
通過指定分區來執行搜尋,提高搜索效率
SELECT * FROM food PARTITION (p1) WHERE id BETWEEN 1 AND 100;
練習
“`=
ALTER TABLE new_food
PARTITION BY RANGE (id) (
PARTITION p1 VALUES LESS THAN (51),
PARTITION p2 VALUES LESS THAN MAXVALUE
);
SELECT * FROM new_food PARTITION (p1) WHERE id BETWEEN 1 AND 20;
```=
CREATE TABLE food_list_partition (id INT PRIMARY KEY, name VARCHAR(255), category VARCHAR(255))
PARTITION BY LIST (category) (PARTITION p_meat VALUES IN ('beef', 'chicken'), PARTITION p_vegetable VALUES IN ('carrot', 'broccoli'), PARTITION p_fruit VALUES IN ('apple', 'banana'), PARTITION p_other VALUES IN (DEFAULT));
SELECT * FROM food_list_partition PARTITION (p_meat);
# 等同於
SELECT * FROM food_list_partition WHERE category IN ('beef', 'chicken');
CREATE TABLE food_hash_partition (id INT PRIMARY KEY, name VARCHAR(255), category VARCHAR(255))
PARTITION BY HASH (id) PARTITIONS 4;
SELECT * FROM food_hash_partition
WHERE id = 1;
查看分區
SELECT TABLE_NAME, PARTITION_NAME, PARTITION_ORDINAL_POSITION, PARTITION_METHOD, PARTITION_DESCRIPTION
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = 'database_name' AND TABLE_NAME = 'table_name'
ORDER BY PARTITION_ORDINAL_POSITION;
# PARTITION_ORDINAL_POSITION:分區的順序位置
# PARTITION_METHOD:使用的分區方法
查看是否啟用分區修剪
SHOW VARIABLES LIKE 'optimizer_switch';
<> 關閉
SET GLOBAL optimizer_switch ='index_condition_pushdown=off';
垂直分割 Vertical Partitioning
一些欄位經常被查詢,而其他欄位很少被查詢、保護敏感數據,可以使用垂直分割
優點: 查詢效率增加,因為列變少了、可以通過限制數據訪問來提高安全性
缺點: 複雜性增加,因為涉及多個表的查詢、可能需要更多的 join 操作、可能需要處理數據一致性和完整性的問題
CREATE TABLE customer_basic_info SELECT id, name, email, address FROM customers;
CREATE TABLE customer_sensitive_info SELECT id, phone_number FROM customers;
水平分割 Horizontal partitioning
需要降低單個表的大小、提高性能可以考慮水平分割
優點: 查詢效率增加、更容易地擴展和分佈數據庫
缺點: 複雜性增加,因為過多的分割表、需要更多的存儲空間和硬件資源
CREATE TABLE orders_2022 SELECT * FROM orders WHERE order_date >= '2022-01-01' AND order_date < '2023-01-01';
CREATE TABLE orders_2023 SELECT * FROM orders WHERE order_date >= '2023-01-01';
主要用於橫向擴展和分散數據,當單個數據庫實例無法應對高流量或大型數據量時,分片可以幫助平衡負載,提高性能並提供更好的擴展性
優點: 可擴展性、單一故障點的影響範圍更小,可用性提高、通過平行處理和分散查詢負載,可以提高數據庫的查詢性能
缺點: 複雜性增加、數據一致性難以維護、數據遷移成本高
-- Shard 1
CREATE TABLE shard1.customers (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), email VARCHAR(50));
-- Shard 2
CREATE TABLE shard2.customers (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(50), email VARCHAR(50));
INSERT INTO shard1.customers SELECT * FROM customers WHERE date_column < '2023-01-01';
INSERT INTO shard2.customers SELECT * FROM customers WHERE date_column >= '2023-01-01';
練習
假設要把 DATABASE travel TABLE food 的資料表分割到兩個資料庫
CREATE DATABASE travel_1;
create database travel_2;
CREATE TABLE travel_1.food_1
SELECT * FROM travel.food WHERE id >= 1 AND id <= 1000;
use travel_1;
select * from food_1;
CREATE TABLE travel_2.food_2
SELECT * FROM travel.food WHERE id >1000;
use travel_2;
select * from food_2;
START TRANSACTION;
-- 獨佔鎖,其他事務無法訪問或修改該數據,直到持有鎖的事務釋放鎖
SELECT * FROM new_food WHERE id = 1 FOR UPDATE;
-- 共享鎖,其他事務也可以訪問這個數據,但是它們不能對數據進行修改
SELECT * FROM new_food WHERE id = 2 LOCK IN SHARE MODE;
COMMIT;
PS 死鎖 Deadlock : 指兩個或多個並發進程在執行過程中,競爭資源或由於彼此通信而造成的僵局,都無法推進下去
# Session 1
BEGIN;
SELECT * FROM table1 WHERE key1 = 1 FOR UPDATE;
# Session 2
BEGIN;
SELECT * FROM table2 WHERE key2 = 2 FOR UPDATE;
# Session 1 is blocked waiting for the lock held by session 2 here
SELECT * FROM table2 WHERE key2 = 2 FOR UPDATE;
解除
SHOW ENGINE INNODB STATUS;
KILL session_id;
同步複製 Synchronous Replication
# 在主數據庫上創建一個新用戶
CREATE USER 'replication_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
# 配置主數據庫my.cnf文件
[mysqld]
log-bin=mysql-bin
server-id=1
# 配置從數據庫my.cnf文件
[mysqld]
server-id=2
# 開始複製
CHANGE MASTER TO MASTER_HOST='master_host_name',
MASTER_USER='replication_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='recorded_log_file_name',
MASTER_LOG_POS=recorded_log_position;
START SLAVE;
非同步複製Asynchronous Replication
# 在主數據庫上創建一個新用戶
CREATE USER 'replication_user'@'%' IDENTIFIED BY 'password';
GRANT REPLICATION SLAVE ON *.* TO 'replication_user'@'%';
# 配置主數據庫my.cnf文件
[mysqld]
log-bin=mysql-bin
server-id=1
#配置從數據庫my.cnf文件
[mysqld]
server-id=2
# 開始複製
CHANGE MASTER TO MASTER_HOST='master_host_name',
MASTER_USER='replication_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='recorded_log_file_name',
MASTER_LOG_POS=recorded_log_position;
START SLAVE;
B+tree 引指向主鍵,主鍵指向行
支持 ACID 符合的事務
使用行級鎖定 (允許多個事務同時對表中的不同行進行讀取和修改操作,同時保持數據的一致性和完整性)
支持外鍵
屬於 Oracle
B-tree 索引直接指向行
不支持ACID
使用表級鎖定 (當一個用戶對表進行讀或寫操作時,其他用戶無法對該表進行任何操作)
插入快速,但更新和刪除可能會產生問題
數據庫崩潰會損壞表,需要手動修復
曾經是 MySQL 的默認引擎
大多數情況下,MySQL 默認使用InnoDB
CREATE TABLE table_name (
column1 datatype,
column2 datatype,
...
) ENGINE=MYISAM;
# 可以改成 ENGINE=InnoDB;
PS>根據InnoDB存儲引擎的默認行為,PRIMARY KEY 和所有的索引數據都是一起存儲,有利於提高數據的查詢速度
文檔導向: MongoDB 是一種文檔導向的數據庫,以 JSON 格式(BSON)存儲數據
動態模式 : MongoDB 使用動態模式,這意味著同一集合中的文檔可以具有不同的字段
、高性能 : MongoDB 具有良好的擴展性,可以輕鬆地橫向擴展到多台服務器
擴展性 : MongoDB 提供高性能的查詢和索引功能,並支持複雜的查詢操作
高可用性 : MongoDB 支持數據的冗餘備份和自動失敗恢復
豐富的查詢語言 : MongoDB 支持查詢嵌套文檔和動態查詢
var field = "size";
var query = {};
query[field] = { $gte: 15 };
db.inventory.find(query);
db.places.createIndex( { location : "2dsphere" } )
db.places.find(
{
location:
{ $near :
{
$geometry: { type: "Point", coordinates: [ -73.9667, 40.78 ] },
$maxDistance: 1000
}
}
}
)