存档

2019年4月 的存档

mysql诡异的改不掉情况

2019年4月10日 没有评论

今天在看丁奇老师的《MySQL实战45讲》时看到一个有趣的思考题,其实蛮考验对mysql知识的理解的。

问题是如下图这种情况:

执行的sql语句如下:

begin;
select * from t; -- q1
update t set c=0 where c=id; --q2
select * from t; --q3

很有意思的是update前后数据是一致的,什么情况下会发生这种想象哪?

其实这道思考题主要考察了对mysql在RR级别下的可重复读和当前读。先来说一下答案,什么情况下会发生这种情况哪?另外1个事务对这4条sql语句做了修改,比如”update t set c = c+1″这种情况。当然update语句应该是发生在q1时刻之后的,不然select的结果就会是我们update之后的结果了啊。

为什么会出现这种情况哪?

这里主要考对mysql可重复读和当前读的理解。在事务中的q1阶段,select以后就创建了对t表的一致性视图,后面所有的操作都会是从这一时刻的一致性视图来读的。接下来其他事务修改了记录,可能表数据就如下了:

mysql> select * from t;
+----+------+
| id | c    |
+----+------+
|  1 |    2 |
|  2 |    3 |
|  3 |    4 |
|  4 |    5 |
+----+------+

这里有一点要强调的是update语句属于当前读,而会更新当前的一致性视图(主要体现在将当前一致性视图相关的 up_limit_id修改为当前row的trx_id),不然如果其他事务有更新提交,就会被漏掉或者说覆盖了啊。因”update t set c=0 where id=c”没有有效的更新记录,如上图中“0 rows affected”,当前一致性视图也不会更新。因此下面的select语句又从一致性视图中读取到了相同的内容!

分类: Mysql 标签:

docker compose保证服务依赖服务启动

2019年4月3日 没有评论

最近在开发一款小型游戏的服务端,目前基本完成开发了,就打算把它们部署到服务器上面。最终选择的方案是使用docker来完成,这个这过程中对我这个docker新人来说遇到了很多问题,当然也学习和成长了很多。今天来说的如何来保证docker中服务的启动顺序问题。

Issue

例如我现在有个和数据交互的db服务,依赖数据服务mysql_db。我使用docker工具是docker-compose,使用其中的depends_on来想解决问题。

db:
    build: ./db
    volumes:
      - /host/path/:/data/log/
    command:  /cmd
    depends_on:
      - mysql_db
    expose:
      - "10050"

是的,这样的配置可以保证db服务会在mysql_db服务启动以后再启动,一定程度来说如果mysql_db能立马完成启动,并准备好对外服务,那么就没有什么问题了。可是不得不面对的一个问题是,mysql_db启动是一个比较耗时的服务,当db服务启动时mysql_db其实还是在服务的启动过程中,并没有准备好来接受db的数据库连接,这样一来就导致了db服务的异常,进而导致所有依赖db服务都会异常。

Solution

docker-compose目前貌似并没有相应的配置参数来解决类似的问题,在google中找到了一个局限性的替代方案,使用entrypoint.sh脚本。在脚本中增加判断依赖服务是否已经准备完毕的判断,如果没有启动就一直等待,直到依赖服务启动以后,再启动脚本。他这里使用nc命令,对于没有nc命令的镜像就需要自己想办法来解决了。例如可以使用golang中的net.Dial来写个尝试连接的工具,当然其他语言类似的库也可以。

#!/bin/sh

#set -x

: ${SLEEP_SECOND:=1}

# 等待服务启动
wait_for() {
    echo Waiting for $1 to listen on $2...
    while ! nc -z $1 $2; do echo waiting...; sleep $SLEEP_SECOND; done
}

wait_for mysql_db 3306

/go/bin/db --config /data/etc/config.json

Dockerfile修改

...
ADD entrypoint.sh /data/script/entrypoint.sh
...

docker-compose.yml修改

db:
    build: ./db
    volumes:
      ...
    command:  /data/script/entrypoint.sh
    depends_on:
      - mysql_db
    expose:
      - "10050"

至此就可以明确保证我们db服务会在mysql_db准备好以后再来进行启动。

参考文章:《docker compose 服务启动顺序控制》