pcntl_fork() and database concurrency

pcntl_fork() and database concurrency

am 23.04.2010 11:09:57 von Andre Lopes

--001485f2717089bd8d0484e3ca65
Content-Type: text/plain; charset=ISO-8859-1

Hi,

I need to write a PHP Script to use with a Crontab. That Crontab will run
every 10 minutes.

I should use pcntl_fork() to prevent concurrency in database queries, but I
don't have sure how to use this PHP function.

The reason for use this function is to prevent that if the Crontab don't do
the Job in 10 minutes, the next Cronjob will not concur with the job in the
background that is running.

My question. There are PostgreSQL examples on how to use this function to
prevent database concurrency?

Best Regards,

--001485f2717089bd8d0484e3ca65
Content-Type: text/html; charset=ISO-8859-1

Hi,

I need to write a PHP Script to use with a Crontab. That Crontab will run every 10 minutes.

I should use pcntl_fork() to prevent concurrency in database queries, but I don't have sure how to use this PHP function.


The
reason for use this function is to prevent that if the Crontab don't do
the Job in 10 minutes, the next Cronjob will not concur with the job in
the background that is running.

My question. There are PostgreSQL examples on how to use this function to prevent database concurrency?

Best Regards,

--001485f2717089bd8d0484e3ca65--

Re: pcntl_fork() and database concurrency

am 23.04.2010 11:24:48 von Andrew McMillan

--=-tr0Wt+gO5IM0sMWCJryK
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Fri, 2010-04-23 at 10:09 +0100, Andre Lopes wrote:
> Hi,
>=20
> I need to write a PHP Script to use with a Crontab. That Crontab will
> run every 10 minutes.
>=20
> I should use pcntl_fork() to prevent concurrency in database queries,
> but I don't have sure how to use this PHP function.
>=20
> The reason for use this function is to prevent that if the Crontab
> don't do the Job in 10 minutes, the next Cronjob will not concur with
> the job in the background that is running.
>=20
> My question. There are PostgreSQL examples on how to use this function
> to prevent database concurrency?

Hi Andre,

A better approach would be to maintain a lock row in a database table,
and let the database control whether another instance should be allowed
to run.

Imagine a state like:

CREATE TABLE concurrency_control (
application TEXT PRIMARY KEY,
i_started TIMESTAMP,
my_pid INT
);

INSERT INTO concurrency_control VALUES( 'myapp' );

Something like;

// Try and own the application processing record
UPDATE concurrency_control
SET i_started =3D current_timestamp,
my_pid =3D $$
WHERE application =3D 'myapp'
AND (i_started IS NULL
OR i_started < (current_timestamp - '2 hours'::interval)

// Check that we owned the application processing record
SELECT * FROM concurrency_control
WHERE application =3D 'myapp' and my_pid =3D $$

.... if we don't get a row, then we quit ...

//
// All the processing goes in here.
//


// Relinquish the application processing record
UPDATE concurrency_control SET i_started =3D NULL, my_pid =3D NULL
WHERE application =3D 'my_app' AND my_pid =3D $$

// Optionally, for extra credit, clean up the dead rows :-)
VACUUM concurrency_control;


This approach has the benefit of just using standard database ACID
compliance to achieve the goal. If there is a race in the first UPDATE,
once must win, and one must not, and only the winner will continue after
the second statement.

It also means that by setting the '2 hours' to something else, you have
an easy lock expiry mechanism.

Cheers,
Andrew.

------------------------------------------------------------ ------------
andrew (AT) morphoss (DOT) com +64(272)DEBIAN
You are not dead yet. But watch for further reports.
------------------------------------------------------------ ------------


--=-tr0Wt+gO5IM0sMWCJryK
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iEYEABECAAYFAkvRZ1wACgkQjJA0f48GgBLuhACcC/JsUbtNUh6uRfzYh20X fV5r
dSQAmQHvBvgj59LQ1Cb0AIEd38EEGKH5
=sbFq
-----END PGP SIGNATURE-----

--=-tr0Wt+gO5IM0sMWCJryK--

Re: pcntl_fork() and database concurrency

am 23.04.2010 23:33:49 von Andre Lopes

--0016364d2d2dd687a50484ee2e77
Content-Type: text/plain; charset=ISO-8859-1

Hi,

Thanks for the reply.

I forgot to said that I will send e-mails in this process, so I need to
interact with the Database and with the PHP.

This approach is valid for this kind of problem?


I have seen some procedures in SQL Server with row locks(I think this is the
term) to the tables in Selects and Updates. PostgreSQL have this mechanisms?

Best Regards,


On Fri, Apr 23, 2010 at 10:24 AM, Andrew McMillan wrote:

> On Fri, 2010-04-23 at 10:09 +0100, Andre Lopes wrote:
> > Hi,
> >
> > I need to write a PHP Script to use with a Crontab. That Crontab will
> > run every 10 minutes.
> >
> > I should use pcntl_fork() to prevent concurrency in database queries,
> > but I don't have sure how to use this PHP function.
> >
> > The reason for use this function is to prevent that if the Crontab
> > don't do the Job in 10 minutes, the next Cronjob will not concur with
> > the job in the background that is running.
> >
> > My question. There are PostgreSQL examples on how to use this function
> > to prevent database concurrency?
>
> Hi Andre,
>
> A better approach would be to maintain a lock row in a database table,
> and let the database control whether another instance should be allowed
> to run.
>
> Imagine a state like:
>
> CREATE TABLE concurrency_control (
> application TEXT PRIMARY KEY,
> i_started TIMESTAMP,
> my_pid INT
> );
>
> INSERT INTO concurrency_control VALUES( 'myapp' );
>
> Something like;
>
> // Try and own the application processing record
> UPDATE concurrency_control
> SET i_started = current_timestamp,
> my_pid = $$
> WHERE application = 'myapp'
> AND (i_started IS NULL
> OR i_started < (current_timestamp - '2 hours'::interval)
>
> // Check that we owned the application processing record
> SELECT * FROM concurrency_control
> WHERE application = 'myapp' and my_pid = $$
>
> ... if we don't get a row, then we quit ...
>
> //
> // All the processing goes in here.
> //
>
>
> // Relinquish the application processing record
> UPDATE concurrency_control SET i_started = NULL, my_pid = NULL
> WHERE application = 'my_app' AND my_pid = $$
>
> // Optionally, for extra credit, clean up the dead rows :-)
> VACUUM concurrency_control;
>
>
> This approach has the benefit of just using standard database ACID
> compliance to achieve the goal. If there is a race in the first UPDATE,
> once must win, and one must not, and only the winner will continue after
> the second statement.
>
> It also means that by setting the '2 hours' to something else, you have
> an easy lock expiry mechanism.
>
> Cheers,
> Andrew.
>
> ------------------------------------------------------------ ------------
> andrew (AT) morphoss (DOT) com +64(272)DEBIAN
> You are not dead yet. But watch for further reports.
> ------------------------------------------------------------ ------------
>
>

--0016364d2d2dd687a50484ee2e77
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Hi,

Thanks for the reply.

I forgot to said that I will send e=
-mails in this process, so I need to interact with the Database and with th=
e PHP.

This approach is valid for this kind of problem?



I have seen some procedures in SQL Server with row locks(I think this is th=
e term) to the tables in Selects and Updates. PostgreSQL have this mechanis=
ms?

Best Regards,


On Fri, Apr =
23, 2010 at 10:24 AM, Andrew McMillan < to:andrew@morphoss.com">andrew@morphoss.com> wrote:

204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<=
div class=3D"h5">On Fri, 2010-04-23 at 10:09 +0100, Andre Lopes wrote:

> Hi,

>

> I need to write a PHP Script to use with a Crontab. That Crontab will<=
br>
> run every 10 minutes.

>

> I should use pcntl_fork() to prevent concurrency in database queries,<=
br>
> but I don't have sure how to use this PHP function.

>

> The reason for use this function is to prevent that if the Crontab

> don't do the Job in 10 minutes, the next Cronjob will not concur w=
ith

> the job in the background that is running.

>

> My question. There are PostgreSQL examples on how to use this function=


> to prevent database concurrency?



Hi Andre,



A better approach would be to maintain a lock row in a database table,

and let the database control whether another instance should be allowed

to run.



Imagine a state like:



CREATE TABLE concurrency_control (

=A0application TEXT PRIMARY KEY,

=A0i_started TIMESTAMP,

=A0my_pid INT

);



INSERT INTO concurrency_control VALUES( 'myapp' );



Something like;



// Try and own the application processing record

UPDATE concurrency_control

=A0 SET i_started =3D current_timestamp,

=A0 =A0 =A0 my_pid =3D $$

=A0WHERE application =3D 'myapp'

=A0 =A0AND (i_started IS NULL

=A0 =A0 =A0 =A0 OR i_started < (current_timestamp - '2 hours'::=
interval)



// Check that we owned the application processing record

SELECT * FROM concurrency_control

=A0 =A0 WHERE application =3D 'myapp' and my_pid =3D $$



.... if we don't get a row, then we quit ...



//

// All the processing goes in here.

//





// Relinquish the application processing record

UPDATE concurrency_control SET i_started =3D NULL, my_pid =3D NULL

=A0WHERE application =3D 'my_app' AND my_pid =3D $$



// Optionally, for extra credit, clean up the dead rows :-)

VACUUM concurrency_control;





This approach has the benefit of just using standard database ACID

compliance to achieve the goal. =A0If there is a race in the first UPDATE,<=
br>
once must win, and one must not, and only the winner will continue after >
the second statement.



It also means that by setting the '2 hours' to something else, you =
have

an easy lock expiry mechanism.



Cheers,

=A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0Andrew.



------------------------------------------------------------ ------------ >
andrew (AT) morphoss (DOT) com =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0 =A0+64(272)DEBIAN

=A0 =A0 =A0 =A0 You are not dead yet. =A0But watch for further reports. >
------------------------------------------------------------ ------------ >





--0016364d2d2dd687a50484ee2e77--

Re: pcntl_fork() and database concurrency

am 24.04.2010 00:27:49 von Andrew McMillan

--=-4z7W422ceVpY8AXjhPw0
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable

On Fri, 2010-04-23 at 22:33 +0100, Andre Lopes wrote:
> Hi,
>=20
> Thanks for the reply.
>=20
> I forgot to said that I will send e-mails in this process, so I need
> to interact with the Database and with the PHP.
>=20
> This approach is valid for this kind of problem?

Sure. You're just storing a row in the database, checking whether you
successfully did so, and quitting if you didn't. It should be valid for
any problem where you don't want two processes to be happening
concurrently.

Equally you could run your PHP program from a shell script and use some
lockfile program to do a similar thing, but I actually think that the
SQL solution is cleaner, and I trust the ACID capabilities of the
database much more than those of the filesystem.


> I have seen some procedures in SQL Server with row locks(I think this
> is the term) to the tables in Selects and Updates. PostgreSQL have
> this mechanisms?

You could use row locking, but I don't think it gives as much potential
for discovering what/why something is locked, and personally I would
consider it likely to be less imediately understood by a programmer
returning to the code in a couple of years. Whereas anyone who does SQL
knows how UPDATE & SELECT work, they probably have to refer to the
manual to work out exactly what LOCK does.

Cheers,
Andrew.

>=20
> Best Regards,
>=20
>=20
> On Fri, Apr 23, 2010 at 10:24 AM, Andrew McMillan
> wrote:
> =20
> On Fri, 2010-04-23 at 10:09 +0100, Andre Lopes wrote:
> > Hi,
> >
> > I need to write a PHP Script to use with a Crontab. That
> Crontab will
> > run every 10 minutes.
> >
> > I should use pcntl_fork() to prevent concurrency in database
> queries,
> > but I don't have sure how to use this PHP function.
> >
> > The reason for use this function is to prevent that if the
> Crontab
> > don't do the Job in 10 minutes, the next Cronjob will not
> concur with
> > the job in the background that is running.
> >
> > My question. There are PostgreSQL examples on how to use
> this function
> > to prevent database concurrency?
> =20
> =20
> Hi Andre,
> =20
> A better approach would be to maintain a lock row in a
> database table,
> and let the database control whether another instance should
> be allowed
> to run.
> =20
> Imagine a state like:
> =20
> CREATE TABLE concurrency_control (
> application TEXT PRIMARY KEY,
> i_started TIMESTAMP,
> my_pid INT
> );
> =20
> INSERT INTO concurrency_control VALUES( 'myapp' );
> =20
> Something like;
> =20
> // Try and own the application processing record
> UPDATE concurrency_control
> SET i_started =3D current_timestamp,
> my_pid =3D $$
> WHERE application =3D 'myapp'
> AND (i_started IS NULL
> OR i_started < (current_timestamp - '2
> hours'::interval)
> =20
> // Check that we owned the application processing record
> SELECT * FROM concurrency_control
> WHERE application =3D 'myapp' and my_pid =3D $$
> =20
> ... if we don't get a row, then we quit ...
> =20
> //
> // All the processing goes in here.
> //
> =20
> =20
> // Relinquish the application processing record
> UPDATE concurrency_control SET i_started =3D NULL, my_pid =3D NUL=
L
> WHERE application =3D 'my_app' AND my_pid =3D $$
> =20
> // Optionally, for extra credit, clean up the dead rows :-)
> VACUUM concurrency_control;
> =20
> =20
> This approach has the benefit of just using standard database
> ACID
> compliance to achieve the goal. If there is a race in the
> first UPDATE,
> once must win, and one must not, and only the winner will
> continue after
> the second statement.
> =20
> It also means that by setting the '2 hours' to something else,
> you have
> an easy lock expiry mechanism.
> =20
> Cheers,
> Andrew.
> =20
> ------------------------------------------------------------ -----=
-------
> andrew (AT) morphoss (DOT) com
> +64(272)DEBIAN
> You are not dead yet. But watch for further reports.
> ------------------------------------------------------------ -----=
-------
> =20
>=20

------------------------------------------------------------ ------------
andrew (AT) morphoss (DOT) com +64(272)DEBIAN
Q: How much does it cost to ride the Unibus?
A: 2 bits.
------------------------------------------------------------ ------------


--=-4z7W422ceVpY8AXjhPw0
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: This is a digitally signed message part

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)

iEYEABECAAYFAkvSHuIACgkQjJA0f48GgBLJugCfXUBWj3Cqk6eDyQMRhEDL Q/SF
2sAAoLTy+ZyOFdyHFSF2PFtrWkSZqsTh
=AZVQ
-----END PGP SIGNATURE-----

--=-4z7W422ceVpY8AXjhPw0--