在 Bash 脚本上,我想在多个顺序访问中保持 MySQL session 打开;访问 MySQL 的常用方法是为每个 SQL 命令或命令集打开一个单独的 session ,例如
mysql -u user -e "show tables;"
这种方法的局限性是那些需要双重事务的原子性和锁定状态的丢失:例如,不可能在整个表 T
上保留锁定状态以下双重操作的长度:
### Minimalistic example
data=$(mysql -e "\
lock table T write;
select col from T;
")
# ...
# parse 'data' and compute 'output' variable
# ...
mysql -e "insert into T values ($output);"
我的解决方案是使用两个 FIFO 使 MySQL session 在多次访问中保持打开状态,并将进程卡在后台。
建议的解决方案:
创建一对 FIFO:mkfifo IN OUT
。
将 MySQL 客户端实例设置到位,并设置一个虚拟 while
以保持管道打开并阻止 SIGPIPE
信号:
mysql --xml --batch --raw --skip-column-names \
-h "$hostname" -u "$username" "$db" >IN <OUT &
while :; do sleep 1; done <IN >OUT &
然后测试一下:
echo "show tables;" >OUT
read <IN
结果:
这没用。 echo
命令完成并且 bash 跳过它,这意味着 MySQL 接收到输入,但是 read
永远挂起,所以没有输出产生。
我发现消除 IN
FIFO 整个任务不会挂起:
mysql --xml --batch --raw --skip-column-names \
-h "$hostname" -u "$username" "$db" <OUT &
while :; do sleep 1; done >OUT &
echo "show tables;" >OUT # this produces the expected output
这种行为是预期的吗?另外我想知道是否可以在没有自定义自制程序的情况下在 Bash 中运行双重操作。
最佳答案
FIFO 的问题在于,当每个输入数据的进程终止时,它会向正在读取数据的进程(在本例中为 mysql
)发出信号,表明数据已结束,因此它会终止。
诀窍是确保有一个进程始终保持 FIFO 输入处于事件状态。您可以通过在后台运行 sleep 999999999 > fifofile
来做到这一点。
例子:
#!/bin/sh
mkfifo /tmp/sqlpipe
sleep 2147483647 > /tmp/sqlpipe &
PID=$!
mysql -B -uUSER -pPASSWORD < /tmp/sqlpipe &
# all set up, now just push the SQL queries to the pipe, exemple:
echo "INSERT INTO table VALUES (...);" > /tmp/sqlpipe
echo "INSERT INTO table VALUES (...);" > /tmp/sqlpipe
echo "INSERT INTO table VALUES (...);" > /tmp/sqlpipe
cat "mysqldump.sql" > /tmp/sqlpipe
echo "DELETE FROM table WHERE ...;" > /tmp/sqlpipe
# done! terminate pipe
kill -s SIGINT $PID
rm /tmp/sqlpipe
最后我们终止sleep
进程以完全释放FIFO 输入。它会向 mysql
发出输入已结束的信号,并因此自动死亡。
还有一个不需要 FIFO 的替代方案,但您需要两个脚本:
运行.sh:
#!/bin/sh
./querygenerator.sh | mysql -B -uUSER -pPASSWORD
querygenerator.sh:
#!/bin/sh
echo "INSERT INTO table VALUES (...);"
echo "INSERT INTO table VALUES (...);"
echo "INSERT INTO table VALUES (...);"
cat "mysqldump.sql"
echo "DELETE FROM table WHERE ...;"
关于mysql - 完全通过 FIFO 连接到 MySQL 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20025209/