如何盡量減少App與MySQL的交互?

2013-04-13 08:39:14來(lái)源:Linux Today作者:

最近研究MySQL應(yīng)用優(yōu)化中討論的一個(gè)問(wèn)題:如何做到在APP端盡量將業(yè)務(wù)邏輯緊密相關(guān)的幾條SQL封裝成單個(gè)SQL批量發(fā)送給Server。這種思路和存儲(chǔ)過(guò)程還不太一樣,另外存儲(chǔ)過(guò)程需要將業(yè)務(wù)邏輯綁定在服務(wù)器端,并且測(cè)試過(guò)程

最近研究MySQL應(yīng)用優(yōu)化中討論的一個(gè)問(wèn)題:如何做到在APP端盡量將業(yè)務(wù)邏輯緊密相關(guān)的幾條SQL封裝成單個(gè)SQL批量發(fā)送給Server。這種思路和存儲(chǔ)過(guò)程還不太一樣,另外存儲(chǔ)過(guò)程需要將業(yè)務(wù)邏輯綁定在服務(wù)器端,并且測(cè)試過(guò)程發(fā)現(xiàn)在效率上要相對(duì)Oracle弱化不少。我們需要的是什么樣的功能呢?

業(yè)務(wù)場(chǎng)景:

舉一個(gè)典型的賬務(wù)邏輯中SQL例子:

begin;
update t1 set xxx where xxx; # 影響兩行記錄
insert into t2 values(); # 成功插入一行記錄
xxxyyyzzz;
commit;

注意,業(yè)務(wù)上非常強(qiáng)的邏輯要求:update必須是成功更新兩條記錄 && insert必須是成功插入一條記錄。

此時(shí)業(yè)務(wù)優(yōu)化希望能將update & insert 封裝成一條邏輯語(yǔ)句,任何一條語(yǔ)句不成功便需要返回錯(cuò)誤,是否回滾則讓APP決定。

為此,MySQL服務(wù)器層必須要擴(kuò)展語(yǔ)法:

update min_batch_rows=2 t1 set xxx where xxx;
insert min_batch_rows=1 into t2 values();

在APP端,將這兩條語(yǔ)句一起發(fā)送給服務(wù)器端(CLIENT_MULTI_STATEMENTS),一旦有一條語(yǔ)句執(zhí)行不成功則中止。

1. 對(duì)單條記錄,需要擴(kuò)展 min_batch_rows 語(yǔ)法,在命令處理完后判斷影響的行數(shù)從而決定是否回滾。
2. 對(duì)多條記錄,需要將這幾條語(yǔ)句批量發(fā)送,這一組連續(xù)的帶hint的語(yǔ)句為一組特殊的語(yǔ)句,要么全做,要么全不做。

1. 單條語(yǔ)句

## min_batch_rows 是指最小影響行數(shù),如果影響的行數(shù)小于此值,則當(dāng)前語(yǔ)句會(huì)被回滾。

# 兩條a=11的記錄

mysql> select * from t1 where a=11;
+------+
| a    |
+------+
|   11 |
|   11 |
+------+
2 rows in set (3.79 sec)
# 指定最小更新量為2,a=11的記錄會(huì)被更新

mysql>  update MIN_BATCH_SIZE=2 t1 set a=a+10 where a=11;
Query OK, 2 rows affected (1.40 sec)
Rows matched: 2  Changed: 2  Warnings: 0

mysql> select * from t1 where a=11;
Empty set (1.18 sec)

mysql> select * from t1 where a=21;
+------+
| a    |
+------+
|   21 |
|   21 |
+------+
2 rows in set (1.94 sec)
# 指定最小更新量為3,a=21的記錄會(huì)不被更新,因?yàn)橹挥袃蓷l記錄有影響

mysql>  update MIN_BATCH_SIZE=3 t1 set a=a+10 where a=21;
ERROR 1721 (HY000): effected rows are less than specified mini_batch_rows.
mysql> select * from t1 where a=21;
+------+
| a    |
+------+
|   21 |
|   21 |
+------+
2 rows in set (1.90 sec)

2. 多條語(yǔ)句

## min_batch_rows 的語(yǔ)句為一組邏輯,只有上條語(yǔ)句正確執(zhí)行后下一條語(yǔ)句才可能會(huì)執(zhí)行。

mysql> delimiter ||
mysql> truncate table t1;
    -> begin;insert into t1 values(1); insert into t1 values(2);  insert into t1 values(3);commit ||


mysql> select * from t1 ||
+------+
| a    |
+------+
|    1 |
|    2 |
|    3 |
+------+
3 rows in set (0.00 sec)

mysql> begin;
    -> update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=1;
    -> update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=2;
    -> update MIN_BATCH_SIZE=2 t1 set a=a+10 where a=3;
    -> commit ||
Query OK, 0 rows affected (0.00 sec)

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

ERROR 1721 (HY000): effected rows are less than specified mini_batch_rows.
mysql>
# 仍舊是原先的123

# 注意,如果在原先的session中查看記錄會(huì)是修改后的記錄,因?yàn)閙ulti-sql被過(guò)截掉了。

delimiter ||
truncate table t1;
begin;insert into t1 values(1); insert into t1 values(2);  insert into t1 val<code>ues(3);commit ||
   
## SQL:  
delimiter ||
begin;
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=1;
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=2;
update MIN_BATCH_SIZE=2 t1 set a=a+10 where a=3;
commit ||


## SQL:
delimiter ||
begin;
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=1;
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=2;
update MIN_BATCH_SIZE=2 t1 set a=a+10 where a=3 ||
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=3;
commit ||

## SQL:
delimiter ||
begin;
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=1;
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=2;
update MIN_BATCH_SIZE=2 t1 set a=a+10 where a=3 ||
update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=3 ||
commit ||
其執(zhí)行結(jié)果:

mysql> delimiter ||
mysql> begin;
    -> update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=1;
    -> update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=2;
    -> update MIN_BATCH_SIZE=2 t1 set a=a+10 where a=3 ||
Query OK, 0 rows affected (0.00 sec)

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

ERROR 1721 (HY000): effected rows are less than specified mini_batch_rows.
mysql> update MIN_BATCH_SIZE=1 t1 set a=a+10 where a=3 ||
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> commit ||
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t1; ||
+------+
| a    |
+------+
|   11 |
|   12 |
|   13 |
+------+
3 rows in set (0.00 sec)

關(guān)鍵詞:AppMySQL

贊助商鏈接: