laravel DB :: транзакция не начинается в потоке - PullRequest
0 голосов
/ 30 октября 2019

Рассмотрим этот код, он довольно понятен:

<?php


class TestController extends BaseController {
    public static $buffer,$num,$stderr;
    public static function test(){
        //phpinfo();
        //print_r(class_exists('Thread'));
        //return;
        self::$stderr=fopen('php://stderr', 'w');
        TestController::$buffer=[];
        TestController::$num=0;
        $t1=new Mytest(0,1,1);
        $t1->start();
        $t2=new Mytest(0.2,1,2);
        $t2->start();
        fprintf(self::$stderr, "begin.\n");//flush();
        //dd(MyTest::$total_time);
        usleep((int)((MyTest::$total_time+0.5)*1e6));
        //dd(microtime(true)-MyTest::$microtime,TestController::$buffer);
        return Response:://make(str_replace("\n",'<br />',TestController::$buffer));
        json(DB::table('test.test')->get());
    }
}

class MyTest extends Thread {
    public $num;
    public static $total_time=0;
    public static $microtime=0;
    //public static $buffer;
    public $t1,$t2,$stderr;
    public function __construct($t1,$t2,$num) {
        $this->t1=$t1;
        $this->t2=$t2;
        $this->num=$num;
        self::$total_time=(self::$total_time<$this->t1+$this->t2)?$this->t1+$this->t2:self::$total_time;
        if (!self::$microtime)
            self::$microtime=microtime(true);
    }
    public function run() {
        $this->stderr=fopen('php://stderr', 'w');
        $num=$this->num;
        //dd(1);
        $this->fprintf(STDERR, "%d begin.\n",$num);
        try {
            $this->fprintf(STDERR, "%d 1.\n", $num);
            DB::transaction(function () use ($num){
                $this->fprintf(STDERR, "%d 2.\n", $num);
                if ($this->t1) usleep((int)($this->t1 * 1e6));
                $this->fprintf(STDERR, "%d 3.\n", $num);
                DB::select(DB::raw('insert into test.test () values ();'));
                $this->fprintf(STDERR, "%d 5.\n", $num);
                if ($this->t2) usleep((int)($this->t2 * 1e6));
                $this->fprintf(STDERR, "%d 6.\n", $num);
                //DB::commit();
            });
            $this->fprintf(STDERR, "%d success.\n", $num);
        } catch (Exception $e){
            $this->fprintf(STDERR, "failed %s.\n", $e);
        }
    }
    public function fprintf(...$args){
        //echo(sprintf('%0.6f: '.$args[1],microtime(true)-self::$microtime,$args[2]));
        fprintf($this->stderr,'%0.6f: '.$args[1],
            microtime(true)-self::$microtime,$args[2]);//flush();
    }
}

Когда я вызываю это, вывод:

0.009376: 1 begin.
0.009407: 1 1.
begin.
0.020410: 2 begin.
0.020451: 2 1.

Но если не использовать потоки, все работает нормально:

        $t1=new Mytest(0,1,1);
        $t1->run();
        $t2=new Mytest(0.2,1,2);
        $t2->run();
...
class MyTest/* extends Thread */{

хорошо работает:

0.000010: 1 begin.
0.000033: 1 1.
0.000650: 1 2.
0.000668: 1 3.
0.001383: 1 5.
1.001610: 1 6.
1.004488: 1 success.
1.004619: 2 begin.
1.004690: 2 1.
1.010701: 2 2.
1.210845: 2 3.
1.215331: 2 5.
2.215501: 2 6.
2.218331: 2 success.
begin.

Есть ли обходной путь?
Кстати,

$ php-zts artisan --version
Laravel Framework version 4.2.17
...